索引
索引是跨多个数据存储区的常见概念。虽然它们在数据存储中的实现可能有所不同,但它们用于提高基于一列(或一组列)的查找效率。
不能使用数据注释创建索引。你可以使用Fluent API来指定单个列的索引,如下所示:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Blog>() .HasIndex(b => b.Url); }
指定多个列的索引:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Person>() .HasIndex(p => new { p.FirstName, p.LastName }); }
按照约定,在用作外键的每个属性(或一组属性)中创建索引。
EF Core对每个不同的属性集只支持一个索引。如果您使用Fluent API在一组属性上配置索引,这些属性已经定义了索引(按照约定或以前的配置),那么您将更改该索引的定义。如果您想要进一步配置根据约定创建的索引,这很有用。
1、唯一索引
默认情况下,索引不是唯一的:允许多行索引的列有相同的值。你可以让一个索引唯一,如下所示:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Blog>() .HasIndex(b => b.Url) .IsUnique(); }
试图为唯一索引的列集插入多个具有相同值的实体将导致抛出异常。
2、索引名称
按照约定,在关系数据库中创建的索引命名为IX_<类型名>_<属性名>。对于复合索引,<属性名>将成为一个下划线分隔的属性名列表。
你可以使用Fluent API来设置在数据库中创建的索引的名称:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Blog>() .HasIndex(b => b.Url) .HasDatabaseName("Index_Url"); }
3、索引筛选器
有些关系数据库允许指定过滤索引或部分索引。这允许您仅为列值的子集建立索引,从而减少索引的大小并提高性能和磁盘空间使用。有关SQL Server过滤索引的更多信息,请参阅文档。
你可以使用Fluent API在索引上指定一个过滤器,它以SQL表达式的形式提供:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Blog>() .HasIndex(b => b.Url) .HasFilter("[Url] IS NOT NULL"); }
当使用SQL Server提供程序时,EF为唯一索引中所有可为空的列添加了一个“IS NOT NULL”过滤器。若要重写此约定,您可以提供一个空值:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Blog>() .HasIndex(b => b.Url) .IsUnique() .HasFilter(null); }
3、包含列
一些关系数据库允许您配置一组列,这些列包含在索引中,但不是索引“键”的一部分。当查询中的所有列都作为键或非键列包含在索引中时,这可以显著提高查询性能,因为表本身不需要被访问。有关SQL Server包含的专栏的更多信息,请参阅文档。
在下面的示例中,Url列是索引键的一部分,因此对该列进行的任何查询过滤都可以使用索引。但除此之外,仅访问Title和PublishedOn列的查询不需要访问表,运行效率更高:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Post>() .HasIndex(p => p.Url) .IncludeProperties(p => new { p.Title, p.PublishedOn }); }