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

一.索引

索引是許多數(shù)據(jù)存儲(chǔ)中的常見(jiàn)概念。雖然它們?cè)跀?shù)據(jù)存儲(chǔ)中的實(shí)現(xiàn)可能會(huì)有所不同,但它們可用于更有效地基于列(或列集)進(jìn)行查找。按照約定,用作外鍵每個(gè)屬性 (或組的屬性) 會(huì)自動(dòng)創(chuàng)建索引。無(wú)法使用數(shù)據(jù)注釋創(chuàng)建索引。

1.1 非唯一索引

Fluent API 在單個(gè)屬性上指定索引。默認(rèn)情況下,索引是非唯一的。如下代碼示例在Blogs表上創(chuàng)建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 復(fù)合索引
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基于數(shù)據(jù)模型(People)創(chuàng)建數(shù)據(jù)表。在Migration中生成了索引的代碼, 以及查看數(shù)據(jù)庫(kù)People表的索引(官方文檔中暫沒(méi)有看到提供索引包含列設(shè)置)如下所示:

 name: "IX_People_FirstName_LastName",
         table: "People",
         columns: new[] { "FirstName", "LastName" });

二.備用鍵

除主鍵之外,備用鍵用作每個(gè)實(shí)體實(shí)例的備用唯一標(biāo)識(shí)符(跟主鍵一樣具有唯一約束)。備用鍵可以用作關(guān)系的目標(biāo)。當(dāng)使用關(guān)系數(shù)據(jù)庫(kù)時(shí),這映射到備用鍵列上的唯一索引/約束的概念以及引用列的一個(gè)或多個(gè)外鍵約束。系統(tǒng)通常會(huì)在需要時(shí)為你引入備用鍵,你無(wú)需手動(dòng)配置它們。不能使用數(shù)據(jù)注釋配置備用鍵。

2.1 約定

按照約定,系統(tǒng)將在識(shí)別屬性(不是主鍵)時(shí)為你引入備用鍵,充當(dāng)關(guān)系的目標(biāo)。如下面代碼所示:

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中創(chuàng)建BlogUrl外建字段
            .HasForeignKey(p => p.BlogUrl)
            //Blog中設(shè)置唯一約束備份鍵
            .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; }
}

上面主體實(shí)體Blog中Url屬性作為備用鍵,創(chuàng)建了AK_Blogs_Url唯一非聚集索引。在依賴(lài)實(shí)體Post中創(chuàng)建了BlogUrl外鍵字段, 使用EF基于數(shù)據(jù)模型(Blog和Post實(shí)體)創(chuàng)建數(shù)據(jù)庫(kù),如下圖所示。


2.2 Fluent API

可以使用Fluent API將單個(gè)屬性配置為備用鍵。

class MyContext : DbContext
{
    public DbSet<Car> Cars { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Car>()
            //配置備用鍵(唯一非聚集索引)
            .HasAlternateKey(c => c.LicensePlate);

            //  創(chuàng)建復(fù)合備用鍵
            //  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 模型中的繼承用于控制如何在數(shù)據(jù)庫(kù)中表示實(shí)體類(lèi)中的繼承, 按照約定,由數(shù)據(jù)庫(kù)提供程序決定如何在數(shù)據(jù)庫(kù)中表示繼承。有關(guān)如何使用關(guān)系數(shù)據(jù)庫(kù)提供程序處理它,請(qǐng)查看”繼承關(guān)系數(shù)據(jù)庫(kù)“。如果模型中明確包含兩個(gè)或多個(gè)繼承類(lèi)型,EF將僅設(shè)置繼承。EF 不會(huì)掃描的基類(lèi)或派生類(lèi)型,可以在模型中包含類(lèi)型,通過(guò)公開(kāi)DbSet 繼承層次結(jié)構(gòu)中每個(gè)類(lèi)型。不能使用數(shù)據(jù)注釋來(lái)配置繼承。

3.1 約定

下面示例中,有二個(gè)實(shí)體,通過(guò)公開(kāi)Dbset類(lèi)型,默認(rèn)約定繼承,如下所示:

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基于數(shù)據(jù)模型(Blog和RssBlog實(shí)體)創(chuàng)建數(shù)據(jù)庫(kù)。生成后,兩個(gè)實(shí)體合并到一個(gè)Blogs表中,如下所示:


3.2 Fluent API

如果您不想公開(kāi)DbSet對(duì)于層次結(jié)構(gòu)中的一個(gè)或多個(gè)實(shí)體,您可以使用Fluent API確保它們包含在模型中。如果您不依賴(lài)約定,則可以使用明確指定基類(lèi)型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示例中,創(chuàng)建了discriminator辨別者隱藏屬性,是基于base entity的層級(jí)。因?yàn)樗悄P椭械囊粋€(gè)屬性,所以可以像配置其他屬性一樣配置它。例如,要設(shè)置默認(rèn)情況下的最大長(zhǎng)度。

modelBuilder.Entity<Blog>()
         .Property("Discriminator")
            .HasMaxLength(200);

discriminator鑒別器也可以映射到實(shí)體中的實(shí)際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; }
}

參考文獻(xiàn):

官方文檔:EF索引

EF備用鍵

EF繼承

EF繼承(關(guān)系數(shù)據(jù)庫(kù))

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容