微軟跨平臺ORM框架之EFCore — 約定與屬性對映
EFCore中的約定簡單來說就是規則,CodeFirst基於模型的約定來對映表結構。除此之外還有Fluent API、Data Annotations(資料註釋) 可以幫助我們進一步配置模型。
按照這三者的優先順序高低排序分別是:Fluent API、Data Annotations(資料註釋)、約定。
1.約定
public class Person { public int ID { get; set; } public int Age { get; set; } public bool Status { get; set; } public string Name { get; set; } public DateTime CreateTime { get; set; } }
1.1 主鍵約定
我們有這樣的一個Person類, 在實體中如果有名為ID的欄位,或者實體名+ID的欄位如:PersonID,那麼EFCore生成的表會自動標識為主鍵。並且如果它的型別是int或Guid則會預設自增長。
對映之後的表結構:
我們可以看到C#中的int、bool、string、datetime,分別對映為 int,bit,navarchar(MAX),datetime2(7)。這是因為EFCore的預設約定是這麼規定的。道友們可能會想自定義的對映,比如把string對映會varcher,datetime對映為datetime。嗯。。這就需要藉助 Fluent API或Data Annotations 了。
1.2 外來鍵約定
新建一個訂單類,並新增Person型別的欄位,以及PersonID(以類名+ID的形式),並在上下文中註冊。EFCore在對映表時會根據我們給定Person型別和PersonID來新增外來鍵約束。
public class Order { public Guid ID { get; set; } public int PersonID { get; set; } public Person Person { get; set; } public string Address { get; set; } public string Phone { get; set; } }
修改Progarm.cs程式碼
class Program { static void Main(string[] args) { var context = new CoreDbContext(); // 刪除資料庫 context.Database.EnsureDeleted(); // 告訴EFCore我們要建立資料庫 context.Database.EnsureCreated(); // 初始化資料 var person = new Person() { Name = "季某人", Age = 11, Status = true, CreateTime = DateTime.Now, }; var person2 = new Person() { Name = "季某人", Age = 11, Status = true, CreateTime = DateTime.Now, }; var order = new Order() { PersonID = 1, Address = "地球XX", Phone = "00000" }; context.Person.Add(person); context.Person.Add(person2); // 這裡因為添加了外來鍵,所以要先儲存Person,不然會報外來鍵的錯誤 context.SaveChanges(); context.Order.Add(order); context.SaveChanges(); //Console.WriteLine("Hello World!"); } }
啟動專案,然後檢視資料庫。
可以看到資料完成了初始化,並且添加了外來鍵約束。
2.Data Annotations(資料註釋)
資料註釋就是在屬性上新增一些特性標籤,告訴EFCore我們要對映的型別是什麼樣的,當預設的對映不能滿足我們的需求時,就可以使用資料註釋了。例如前面的對映,string型別對映為資料庫的nvarchar(max),DateTime對映為datetime2(7)。 使用資料註釋可以改變為我們想要對映成的型別,例如:string對映成varvhar。
新增一個新類OrderDetail,並新增資料註釋。
public class OrderDetail { [Key] // 標識主鍵 public int ID { get; set; } [Column(TypeName = "varchar(50)")] // 列的資料型別 [Required] // 必填列 public string Price { get; set; } public DateTime? CreateTime { get; set; } [Column("OrderCode")] // 列的顯示名字 [StringLength(50)] // 列的長度 public string Code { get; set; } public Guid? OrderID { get; set; } public Order Order { get; set; } }
啟動專案,觀察對映成的表結構。與實體中的配置一樣。
基本常用的就這些,其他的用到的時候可以去官網文件上找。
3.Fluent API
Fluent API 相較於 資料註釋更加靈活。它的配置需要寫在自定義的上下文類中的OnModelCreating方法中。
比如改變表名,資料型別之類的
效果和資料註釋是一樣的,值得注意的是當Fluent API 和資料註釋同時配置一個屬性時,Fluent API會覆蓋掉資料註釋。
除了上述之外還可以利用Fluent API 統一表的命名規範:例如 "T_+實體名".
protected override void OnModelCreating(ModelBuilder modelBuilder) { foreach (var item in modelBuilder.Model.GetEntityTypes()) { modelBuilder.Entity(item.Name).ToTable("T_" + item.ClrType.Name); } }
遍歷要對映的實體然後加上 "T_" 字首。
具體差異可以觀看微軟EFCore文件,傳送門:https://docs.microsoft.com/zh-cn/ef/core/modeling/relational/data-types