asp.net core系列 27 EF模型配置(索引,備用鍵,繼承)


一.索引

  索引是許多數據存儲中的常見概念。雖然它們在數據存儲中的實現可能會有所不同,但它們可用於更有效地基於列(或列集)進行查找。按照約定,用作外鍵每個屬性 (或組的屬性) 會自動創建索引。無法使用數據注釋創建索引。

  

  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索引

           EF備用鍵

         EF繼承

         EF繼承(關系數據庫)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM