針對關係型資料庫,實體之間的關係最常見的就是通過外鍵關聯的一對一、一對多和多對多的關係,新的EF Core通過註釋和Fluent API 能夠做到接近於資料庫通過DML創建模型的效果了。實際上,通過DML 最大的優勢在於,能夠定義所謂的Independent/Dependent Entity具體的那 ...
針對關係型資料庫,實體之間的關係最常見的就是通過外鍵關聯的一對一、一對多和多對多的關係,新的EF Core通過註釋和Fluent API 能夠做到接近於資料庫通過DML創建模型的效果了。實際上,通過DML 最大的優勢在於,能夠定義所謂的Independent/Dependent Entity具體的那個欄位作為關聯欄位,而EF更多通過一種約定去描述這種關聯關係,不過通過Fluent API 能夠收工定義的操作範圍更近廣了。
下麵的這個表關係實際上描述了大部分關係型資料庫的關聯關係,能夠覆蓋大部分場景,通過這個例子去說明Code First 創建實體的標準方法。
Members 和Tasks 關係,Member是Independent Entity, Tasks是Dependent Entity,定義類如下:
namespace MemberTask.Models { public partial class Members { [Key] public int? MemberId { get; set; } public string MemberName { get; set; } [InverseProperty("Members")] public List<Tasks> Tasks { get; set; } } }
namespace MemberTask.Models
{
public partial class Tasks
{
[Key]
public int? TaskId { get; set; }
public int TaskName { get; set; }
public int MemberId { get; set; }
[ForeignKey("MemberId")]
public Members Members { get; set; }
//part of many2many
[InverseProperty("Task")]
public List<TaskAndOaTasksR> TaskAndOaTasksRs { get; set; }
}
}
在這兩個實體的關係中:
先看Tasks類(紅色字體部分),通過註釋指明,MemberId 欄位作為外鍵,而Members引用導航屬性,作為外鍵所關聯依賴的對象。
Members類,Tasks 列表導航屬性就是被引用對象,而註釋表明Members 就是Tasks中的引用導航屬性Members。
另外3個實體店關係為,Tasks和OaTasks是業務實體,TaskAndOaTasksRs實際上作為一個中間表,提供一種多對多的關係,這種模式實際上是作為靈活的一種實體模式,雖然有一定的空間損耗,但是無論哪種關係,或者未來需要擴展成為多對多的關係可以隨時實施。
OaTasks:
namespace MemberTask.Models { public partial class OaTasks { [Key] public int? OaTaskId { get; set; } public string OaTaskName { get; set; } [InverseProperty("OaTask")] public List<TaskAndOaTasksR> TaskAndOaTasksRs { get; set; } } }
TasksAndOaTasksRs:
namespace MemberTask.Models { public partial class TaskAndOaTasksR { public int? TaskId { get; set; } [ForeignKey("TaskId")] public Tasks Task { get; set; } [ForeignKey("OaTaskId")] public int? OaTaskId { get; set; } public OaTasks OaTask { get; set; } } }
TasksAndOaTasksRs在實際上使用的時候,是不需要實現TaskId查詢關聯的多個OaTaskId的,僅僅查詢TaskId & OaTaskId 的一一對應關係,因此通過引用導航屬性引用Tasks 和OaTasks。相反,Tasks 和OaTasks都有需要進行一對多關聯查詢,因此採用了列表導航屬性。
模型建好後,根據實際情況配置DbContext,特別是針對外鍵關聯,根據實際情況定義好OnDelete方法。
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Members>() .Property(b => b.MemberId).ValueGeneratedNever(); modelBuilder.Entity<Tasks>() .Property(t => t.TaskId).ValueGeneratedNever(); modelBuilder.Entity<OaTasks>() .Property(o => o.OaTaskId).ValueGeneratedNever(); modelBuilder.Entity<Tasks>() .HasOne(m=>m.Members) .WithMany(t=>t.Tasks) .OnDelete(DeleteBehavior.Cascade); // below is for many2many modelBuilder.Entity<TaskAndOaTasksR>() .HasOne(t => t.Task) .WithMany(tt => tt.TaskAndOaTasksRs); modelBuilder.Entity<TaskAndOaTasksR>() .HasOne(t => t.OaTask) .WithMany(tt => tt.TaskAndOaTasksRs); modelBuilder.Entity<TaskAndOaTasksR>() .HasKey(t => new {t.TaskId, t.OaTaskId}); }
運行資料庫更新命令,實體和資料庫模型就建好了。