Для увеличения производительности поиска в базе данных применяются индексы. По умолчанию индекс создается для каждого свойства, которое используется в качестве внешнего ключа. Однако Entity Framework также позволяет создавать свои индексы.
Для создания индекса можно использовать атрибут [Index]. Например:
using Microsoft.EntityFrameworkCore; [Index("PhoneNumber")] public class User { public int Id { get; set; } public string? Name { get; set; } public string? Passport { get; set; } public string? PhoneNumber { get; set; } }
Первый и обязательный параметр атрибута указывает на свойство (или набор свойств), с которым будет ассоциирован индекс. В данном случае это свойство PhoneNumber.
Но также он может принимать набор свойств, для которых создается индекс. В этом случае названия свойств просто перечисляются через запятую:
using Microsoft.EntityFrameworkCore; [Index("PhoneNumber", "Passport")] public class User { public int Id { get; set; } public string? Name { get; set; } public string? Passport { get; set; } public string? PhoneNumber { get; set; } }
С помощью дополнительных параметров можно настроить уникальность и имя индекса:
using Microsoft.EntityFrameworkCore; [Index("PhoneNumber", IsUnique = true, Name ="Phone_Index")] public class User { public int Id { get; set; } public string? Name { get; set; } public string? Passport { get; set; } public string? PhoneNumber { get; set; } }
В данном случае индекс будет называться Phone_Index, а значение IsUnique = true
указывает, что индекс должен быть уникальным.
Для создания индекса через Fluent API применяется метод HasIndex():
using Microsoft.EntityFrameworkCore; public class ApplicationContext : DbContext { public DbSet<User> Users { get; set; } = null!; public ApplicationContext() { Database.EnsureDeleted(); Database.EnsureCreated(); } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlite("Data Source=helloapp.db"); } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<User>().HasIndex(u => u.Passport); } } public class User { public int Id { get; set; } public string? Name { get; set; } public string? Passport { get; set; } public string? PhoneNumber { get; set; } }
С помощью дополнительного метода IsUnique() можно указать, что индекс должен иметь уникальное значение. Тем самым мы гарантируем, что в базе данных может быть только один объект с определенным значением для свойства-индекса:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<User>().HasIndex(u => u.Passport).IsUnique(); }
Также можно определить индексы сразу для нескольких свойств:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<User>().HasIndex(u => new { u.Passport, u.PhoneNumber }); }
Для установки имени индекса применяется метод HasDatabaseName(), в который передается имя индекса:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<User>() .HasIndex(u => u.PhoneNumber) .HasDatabaseName("PhoneIndex"); }
В данном случае для индекса будет использоваться свойство PhoneNumber, а называться он будет "PhoneIndex".
Некоторые системы управления базами данных позволяют определять индексы с фильрами или частичные индексы, которые позволяют выполнять индексацию только по ограниченному набору значений, что увеличивает производительность и уменьшает использование дискового простанства. И EntityFramework Core также позволяет создавать подобные индексы. Для этого применяется метод HasFilter(), в который передается sql-выражение, которое определяет условие фильтра. Например:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<User>() .HasIndex(u => u.PhoneNumber) .HasFilter("[PhoneNumber] IS NOT NULL"); }
В данном случае в качестве индекса будет использоваться столбец PhoneNumber. Причем только для тех строк, у которых в столбце PhoneNumber значение не равно NULL.