(23)ASP.NET Core EF關係數據庫建模

  • 2019 年 11 月 5 日
  • 筆記

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; }  }

參考文獻:
表映射
列映射
數據類型
主鍵
默認架構
默認值
索引(關係數據庫)