1. 程式人生 > >(23)ASP.NET Core EF關係資料庫建模

(23)ASP.NET Core EF關係資料庫建模

1.簡介

一般而言,本部分中的配置適用於關係資料庫。安裝關係資料庫提供程式時,此處顯示的變為可用擴充套件方法(原因在於共享的Microsoft.EntityFrameworkCore.Relational包)。

2.表對映

表對映標識在資料庫中哪張表應該進行內容查詢和儲存操作。

2.1約定

按照約定,每個實體將設定為對映到名稱與DbSet<TEntity> 屬性(公開派生上下文中的實體)相同的表中。如果給定DbSet<TEntity>實體中不包含,則使用類名稱。

2.2資料註釋

可以使用資料註釋來配置型別對映表。

[Table("blogs")]
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

你還可以指定表所屬的架構(資料庫)。

[Table("blogs", Schema = "blogging")]
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

2.3Fluent API

你可以使用熟知的API來配置型別對映到的表。

class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .ToTable("blogs");
    }
}
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

你還可以指定表所屬的架構(資料庫)。

modelBuilder.Entity<Blog>().ToTable("blogs", schema: "blogging");

3.列對映

列對映標識在資料庫中應從哪些列資料中進行查詢和儲存。

3.1約定

按照約定,每個屬性將會設定為對映到與屬性具有相同名稱的列。

3.2資料註釋

可以使用資料註釋來配置屬性對映到的那一列。

namespace EFModeling.DataAnnotations.Relational.Column
{
    class MyContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
    }
    public class Blog
    {
        [Column("blog_id")]
        public int BlogId { get; set; }
        public string Url { get; set; }
    }
}

3.3Fluent API

您可以使用熟知的API來配置屬性對映到的列。

namespace EFModeling.FluentAPI.Relational.Column
{
    class MyContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Blog>()
                .Property(b => b.BlogId)
                .HasColumnName("blog_id");
        }
    }
    public class Blog
    {
        public int BlogId { get; set; }
        public string Url { get; set; }
    }
}

4.資料型別

資料型別是指屬性所對映到的列的資料庫特定型別。

4.1約定

按照約定,資料庫提供程式基於屬性的.NET型別選擇資料型別。它還會考慮其他元資料,如配置的最大長度、屬性是否是主鍵的一部分等。例如,SQL Server的DateTime、nvarchar(max) 用作鍵的屬性。

4.2資料註釋

您可以使用資料註釋為列指定精確的資料型別。例如,下面的程式碼將Url配置為一個非unicode字串,其最大200長度。Rating為5至2小數位。

public class Blog
{
    public int BlogId { get; set; }
    [Column(TypeName = "varchar(200)")]
    public string Url { get; set; }
    [Column(TypeName = "decimal(5, 2)")]
    public decimal Rating { get; set; }
}

4.3Fluent API

你還可以使用熟知的API為列指定相同的資料型別。

class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>(eb =>
        {
            eb.Property(b => b.Url).HasColumnType("varchar(200)");
            eb.Property(b => b.Rating).HasColumnType("decimal(5, 2)");
        });
    }
}
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
    public decimal Rating { get; set; }
}

5.主鍵

為每個實體型別的鍵引入primary key(主鍵)約束。

5.1約定

按照約定,會將資料庫中的主鍵命名為PK_<type name>。

5.2資料註釋

不能使用資料批註配置主鍵的關係資料庫的特定方面。

5.3Fluent API

你可以使用API在資料庫中配置primary key(主鍵)約束的名稱。

class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .HasKey(b => b.BlogId)
            .HasName("PrimaryKey_BlogId");
    }
}
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

6.預設架構

如果沒有為該物件顯式配置架構,則預設架構為將在其中建立物件的資料庫架構。

6.1約定

按照約定,資料庫提供程式將選擇最適合的預設架構。例如,Microsoft SQL Server將使用dbo架構,而且sqlite將不使用架構(因為sqlite不支援架構)。

6.2資料註釋

不能使用資料批註設定預設架構。

6.3Fluent API

可以使用API來指定預設架構。

class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.HasDefaultSchema("blogging");
    }
}

7.預設值

如果插入新行,但沒有為該列指定值,則列的預設值為要插入的值。

7.1約定

按照約定,未配置預設值。

7.2資料註釋

不能使用資料批註設定預設值。

7.3Fluent API

你可以使用API指定屬性的預設值。

class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .Property(b => b.Rating)
            .HasDefaultValue(3);
    }
}
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
    public int Rating { get; set; }
}

還可以指定用於計算預設值的SQL片段。

class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .Property(b => b.Created)
            .HasDefaultValueSql("getdate()");
    }
}
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
    public DateTime Created { get; set; }
}

8.索引(關係資料庫)

關係資料庫中的索引對映到與實體框架核心中的索引相同的概念。

8.1約定

按照約定,索引命名為IX_<type name>_<property name>。對於複合索引<property name>,將成為以下劃線分隔的屬性名稱列表。

8.2資料註釋

不能使用資料批註配置索引。

8.3Fluent API

你可以使用熟知的API來配置索引的名稱。

class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .HasIndex(b => b.Url)
            .HasName("Index_Url");
    }
}
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

你還可以指定篩選器。

class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .HasIndex(b => b.Url)
            .HasFilter("[Url] IS NOT NULL");
    }
}
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

使用SQL Server提供程式EF為唯一索引中包含的所有可以為null的列新增"IS NOT NULL"篩選器。若要重寫此約定,可以null提供一個值。

class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .HasIndex(b => b.Url)
            .IsUnique()
            .HasFilter(null);
    }
}
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

在SQL Server索引中包含列,當查詢中的所有列都作為鍵列或非鍵列包含在索引中時,可以通過包含列配置索引以顯著提高查詢效能。

class MyContext : DbContext
{
    public DbSet<Post> Posts { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Post>()
            .HasIndex(p => p.Url)
            .IncludeProperties(p => new
            {
                p.Title,
                p.PublishedOn
            })
            .HasName("Index_Url_Include_Title_PublishedOn");
    }
}
public class Post
{
    public int PostId { get; set; }
    public string Url { get; set; }
    public string Title { get; set; }
    public DateTime PublishedOn { get; set; }
}


參考文獻:
表對映
列對映
資料型別
主鍵
預設架構
預設值
索引(關係資料