一.索引
索引是許多數據存儲中的常見概念。雖然它們在數據存儲中的實現可能會有所不同,但它們可用於更有效地基於列(或列集)進行查找。按照約定,用作外鍵每個屬性 (或組的屬性) 會自動創建索引。無法使用數據注釋創建索引。
1.1 非唯一索引
Fluent API 在單個屬性上指定索引。默認情況下,索引是非唯一的。如下代碼示例在Blogs表上創建Url列索引:
class MyContext : DbContext { public DbSet<Blog> Blogs { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Blog>() .HasIndex(b => b.Url); } }
1.2 唯一索引
下面代碼指定索引是唯一的,這是在索引上加了(Unique)唯一約束。
modelBuilder.Entity<Blog>() .HasIndex(b => b.Url) .IsUnique();
1.3 復合索引
class MyContext : DbContext { public DbSet<People> People { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Person>() .HasIndex(p => new { p.FirstName, p.LastName }); } } public class People { public int PersonId { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string Address{get;set;} }
下面使用EF基於數據模型(People)創建數據表。在Migration中生成了索引的代碼, 以及查看數據庫People表的索引(官方文檔中暫沒有看到提供索引包含列設置)如下所示:
name: "IX_People_FirstName_LastName", table: "People", columns: new[] { "FirstName", "LastName" });

二.備用鍵
除主鍵之外,備用鍵用作每個實體實例的備用唯一標識符(跟主鍵一樣具有唯一約束)。備用鍵可以用作關系的目標。當使用關系數據庫時,這映射到備用鍵列上的唯一索引/約束的概念以及引用列的一個或多個外鍵約束。系統通常會在需要時為你引入備用鍵,你無需手動配置它們。不能使用數據注釋配置備用鍵。
2.1 約定
按照約定,系統將在識別屬性(不是主鍵)時為你引入備用鍵,充當關系的目標。如下面代碼所示:
class MyContext : DbContext { public DbSet<Blog> Blogs { get; set; } public DbSet<Post> Posts { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Post>() .HasOne(p => p.Blog) .WithMany(b => b.Posts) //Post中創建BlogUrl外建字段 .HasForeignKey(p => p.BlogUrl) //Blog中設置唯一約束備份鍵 .HasPrincipalKey(b => b.Url); } } public class Blog { public int BlogId { get; set; } public string Url { get; set; } public List<Post> Posts { get; set; } } public class Post { public int PostId { get; set; } public string Title { get; set; } public string Content { get; set; } public string BlogUrl { get; set; } public Blog Blog { get; set; } }
上面主體實體Blog中Url屬性作為備用鍵,創建了AK_Blogs_Url唯一非聚集索引。在依賴實體Post中創建了BlogUrl外鍵字段, 使用EF基於數據模型(Blog和Post實體)創建數據庫,如下圖所示。

2.2 Fluent API
可以使用Fluent API將單個屬性配置為備用鍵。
class MyContext : DbContext { public DbSet<Car> Cars { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Car>() //配置備用鍵(唯一非聚集索引) .HasAlternateKey(c => c.LicensePlate); // 創建復合備用鍵 // modelBuilder.Entity<Car>() // .HasAlternateKey(c => new { c.State, c.LicensePlate }); } } class Car { public int CarId { get; set; } public string LicensePlate { get; set; } public string Make { get; set; } public string Model { get; set; } public string State { get; set; } }
三.繼承
EF 模型中的繼承用於控制如何在數據庫中表示實體類中的繼承, 按照約定,由數據庫提供程序決定如何在數據庫中表示繼承。有關如何使用關系數據庫提供程序處理它,請查看”繼承關系數據庫“。如果模型中明確包含兩個或多個繼承類型,EF將僅設置繼承。EF 不會掃描的基類或派生類型,可以在模型中包含類型,通過公開DbSet 繼承層次結構中每個類型。不能使用數據注釋來配置繼承。
3.1 約定
下面示例中,有二個實體,通過公開Dbset類型,默認約定繼承,如下所示:
class MyContext : DbContext { public DbSet<Blog> Blogs { get; set; } public DbSet<RssBlog> RssBlogs { get; set; } } public class Blog { public int BlogId { get; set; } public string Url { get; set; } } public class RssBlog : Blog { public string RssUrl { get; set; } }
使用EF基於數據模型(Blog和RssBlog實體)創建數據庫。生成后,兩個實體合並到一個Blogs表中,如下所示:


3.2 Fluent API
如果您不想公開DbSet對於層次結構中的一個或多個實體,您可以使用Fluent API確保它們包含在模型中。如果您不依賴約定,則可以使用明確指定基類型HasBaseType。
class MyContext : DbContext { public DbSet<Blog> Blogs { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<RssBlog>().HasBaseType<Blog>(); } }
3.3 discriminator隱藏屬性
上面3.1示例中,創建了discriminator辨別者隱藏屬性,是基於base entity的層級。因為它是模型中的一個屬性,所以可以像配置其他屬性一樣配置它。例如,要設置默認情況下的最大長度。
modelBuilder.Entity<Blog>() .Property("Discriminator") .HasMaxLength(200);
discriminator鑒別器也可以映射到實體中的實際CLR屬性
class MyContext : DbContext { public DbSet<Blog> Blogs { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Blog>() .HasDiscriminator<string>("BlogType"); } } public class Blog { public int BlogId { get; set; } public string Url { get; set; } //discriminator public string BlogType { get; set; } } public class RssBlog : Blog { public string RssUrl { get; set; } }
參考文獻:
官方文檔:EF索引
