一.模型配置概述 EF使用一組約定基於實體類的定義來構建模型。 可指定其他配置以補充或替代約定的內容。本系列介紹的配置可應用於面向任何數據存儲的模型,以及面向任意關係資料庫時可應用的配置。 資料庫提供程式還可支持特定於具體數據存儲的配置,如Microsoft.EntityFrameworkCore. ...
一.模型配置概述
EF使用一組約定基於實體類的定義來構建模型。 可指定其他配置以補充或替代約定的內容。本系列介紹的配置可應用於面向任何數據存儲的模型,以及面向任意關係資料庫時可應用的配置。
資料庫提供程式還可支持特定於具體數據存儲的配置,如Microsoft.EntityFrameworkCore.SqlServer,Pomelo.EntityFrameworkCore.MySql 等,對於特定配置的文檔參考資料庫提供程式。
1.1 使用 fluent API 配置模型
可在派生上下文中重寫 OnModelCreating
方法,並使用 ModelBuilder API
來配置模型。 此配置方法最為有效,並可在不修改實體類的情況下指定配置。 Fluent API 配置具有最高優先順序,並將替代約定和數據註釋。下麵示例指定Blog類型的Url在保存時必填。如下所示:
class MyContext : DbContext { public DbSet<Blog> Blogs { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Blog>() .Property(b => b.Url) .IsRequired(); } }
1.2 使用數據註釋來配置模型
也可將特性(稱為數據註釋)應用於類和屬性。 數據註釋會替代約定,但會被 Fluent API 配置替代。下麵示例指定Blog類型的Url在保存時必填。如下所示:
public class Blog { public int BlogId { get; set; }
[Required(ErrorMessage = "請輸入URL")] public string Url { get; set; } public ICollection<Post> Posts { get; set; } }
[HttpPost] public async Task<IActionResult> Create([Bind("Url")] Blog blog) { if (ModelState.IsValid) { BloggingContext.Add<Blog>(blog); await BloggingContext.SaveChangesAsync(); } return View(); }
在MVC中, 新增一條Blog數據,Url 欄位為空(包含空格),點擊提交時,在後臺Create中驗證,設置斷點查看ModelState.IsValid為false。
其中取Url欄位的ErrorMessage信息是:ModelState["URL"].Errors[0].ErrorMessage
二.類型的包含和排除約定
將類型(實體類型)包含到模型中意味著,EF會有該類型的元數據,並且會嘗試從資料庫讀取實例(讀取對應的數據表),以及將實例(實體對象數據)寫入到資料庫中。按照約定,在上下文的 DbSet
屬性中公開的類型(實體類型)會包含在模型中。 此外,在 OnModelCreating
方法中提及的類型(實體類型)也將包含在其中。 最後,通過以遞歸方式瀏覽已發現類型的導航屬性而找到的任何類型也會包含在模型中。下麵舉例一 一說明:
2.1 類型包含約定
class MyContext : DbContext { //公開Blog類型,將與資料庫表產生映射關係 public DbSet<Blog> Blogs { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { //公開AuditEntry類型,將與資料庫表產生映射關係 modelBuilder.Entity<AuditEntry>(); } } public class Blog { public int BlogId { get; set; } public string Url { get; set; } //公開Post類型,通過導航屬性。將與資料庫表產生映射關係 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 Blog Blog { get; set; } } public class AuditEntry { public int AuditEntryId { get; set; } public string Username { get; set; } public string Action { get; set; } }
上面示例中:
(1)Blog
,因為它是在上下文的 DbSet
屬性中公開的。(2)Post
,因為它是通過 Blog.Posts
導航屬性發現的。(3) AuditEntry
,因為它在 OnModelCreating
中提及。
2.2 類型排除約定
(1)可以使用數據註釋來從模型中排除類型。
public class Blog { public int BlogId { get; set; } public string Url { get; set; } public BlogMetadata Metadata { get; set; } } [NotMapped] public class BlogMetadata { public DateTime LoadedFromDatabase { get; set; } }
(2)也可以通過Fluent API 把模型中類型排除。
class MyContext : DbContext { public DbSet<Blog> Blogs { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Ignore<BlogMetadata>(); } } public class Blog { public int BlogId { get; set; } public string Url { get; set; } public BlogMetadata Metadata { get; set; } } public class BlogMetadata { public DateTime LoadedFromDatabase { get; set; } }
三.屬性的包含和排除約定
模型中包含屬性意味著 EF 擁有該屬性的元數據,並將嘗試從資料庫讀取值或者向資料庫寫入值。按照約定,模型所含的那些公共屬性都擁有一個 getter 和一個 setter。
3.1 數據註釋
可以使用數據註釋方式來從模型中排除某個屬性
public class Blog { //公開的屬性 public int BlogId { get; set; } public string Url { get; set; } //排除的屬性 [NotMapped] public DateTime LoadedFromDatabase { get; set; } }
3.2 Fluent API
也可以用Fluent API 從模型中排除某個屬性。
class MyContext : DbContext { public DbSet<Blog> Blogs { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Blog>().Ignore(b => b.LoadedFromDatabase); } } public class Blog { public int BlogId { get; set; } public string Url { get; set; } public DateTime LoadedFromDatabase { get; set; } }
參考文獻:
官方資料:創建並配置模型