1. 程式人生 > >Entity Framework 4.1 之二 : 覆蓋預設的約定

Entity Framework 4.1 之二 : 覆蓋預設的約定

原文名稱:Entity Framework 4.1: Override conventions (2) 在這篇文章中,我將討論如何覆蓋預設的約定。 我們已經看過了在 EF4.1 Code First 中模型與資料庫中的預設約定。當這些約定不能滿足我們的時候,我們有兩種不同的途徑來覆蓋這些約定:
  • 攔截模型的構建器,使用流暢的 API 來修改模型
  • 為我們的模型增加標籤
在未來的版本中,我們還將有能力增加或者刪除約定,現在還沒有提供這個能力。 對於我們基本的例子,我們使用下面所示的訂單類。
publicclass Order 
{
publicint OrderID { get; set; }
publicstring OrderTitle { get; set; }
publicstring CustomerName { get; set; }
public DateTime TransactionDate { get; set; }
}

構建器

我們從模型的構建器開始吧。為了使用模型構建器,我們必須重寫 DbContext 的一個方法 OnModelCreating.
protectedoverridevoid OnModelCreating(DbModelBuilder modelBuilder) 
{
base.OnModelCreating(modelBuilder);
// Map schemas modelBuilder.Entity<Order>().ToTable("efdemo.Order");
}
預設情況下,EF 將實體對映到資料庫中 dbo 架構下的同名表上,這裡我將訂單對映到資料庫中 efdemo 架構下的 Order 表。 模型構建器提供了一種流暢的 API 方式,由於方法返回同樣的物件,意味著可以使用鏈式的方法將操作連線在一起。下面是另外一個例子。
modelBuilder.Entity
<Order>().Property(x => x.OrderID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
.IsRequired()
.HasColumnName(
"TheOrderID");
 在這裡,我們對屬性 OrderID 做了三件事:
  • 標識它是標識列,自增長的列
  • 必須的列,非空
  • 對映到資料庫中的 TheOrderID
這裡,我們將涉及 EF4.1 的強大的功能:通過 Lambda 表示式,可以逐條定義屬性,而不是使用字串來標識屬性,這有以下的優勢:
  • 有智慧提示
  • 有編譯時的錯誤檢查
  • 屬性的型別是已知的,你可以在之後定義,例如,只有字串可以有最大或最小長度。
那麼,通常我們重寫什麼約定呢?看一下 Order 類,下面的情況不太符合預設約定:
  • 表必須屬於 dbo Schema
  • OrderID 是主鍵,但不是自增長的型別
  • 所有其他列是非空的
  • 字串列的長度是 128
 我們可以通過模型構建器重寫這些約定:
//    Map schemas modelBuilder.Entity<Order>().ToTable("efdemo.Order"); 
// Identity Column modelBuilder.Entity<Order>().Property(x => x.OrderID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
// String columns modelBuilder.Entity<Order>().Property(x => x.OrderTitle)
.IsRequired()
.HasMaxLength(
64);
modelBuilder.Entity
<Order>().Property(x => x.CustomerName)
.IsRequired()
.HasMaxLength(
32);
// Date Columns modelBuilder.Entity<Order>().Property(x => x.TransactionDate)
.IsRequired();
 看起來有點冗長,但是不用修改模型,純粹的 POCO.

使用標註

現在,我們在看一下另外一種方式,使用標籤。 這種方式的程式碼要少得多,感覺更加自然,通過標籤來說明屬性。唯一的問題是你的類不再 POCO,雖然使用的類並沒有來自 EF,而是 System.ComponentModel.DataAnnotations , .NET 的驗證模組。看一下例子吧。
publicclass Order 
{
publicint OrderID { get; set; }

[Required]
[StringLength(
32, MinimumLength =2)]
publicstring OrderTitle { get; set; }

[Required]
[StringLength(
64, MinimumLength =5)]
publicstring CustomerName { get; set; }

[Required]
public DateTime TransactionDate { get; set; }
}
這裡我們告訴模型構建器將 OrderTitle 對映到非空的長度為32 的 nvarchar 列,最小長度為 2沒有對映到架構中,但是將被用來驗證。 這個例子我給出了一些業務標註,也可以加上一些技術標註。
publicclass Order 
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
publicint OrderNumber { get; set; }

}
這裡我們強制 OrderNumber 屬性作為主鍵,而且是一個自增長的列。 還可以使用 OnModelCreated 或者其他的標籤來覆蓋約定,有一些限制需要注意,例如(這是我注意到的):
  • 表名不支援使用標籤進行標註
  • 最小長度在 OnModelCreated 中不支援
  • 正則表示式在 OnModelCreated 中不支援
著比較好理解,OnModelCreated 屬於表對映,(正則或者最小長度不能在資料庫中表示),標註支援常見的驗證。 我的原則:
  • 使用標註來豐富模型的驗證規則
  • 使用 OnModelCreated 來完成資料庫的約束(主鍵,自增長,表名,列型別等等)
這些方式可以使你的模型更加豐富而且保持 POCO,你可以到處重用你的模型,還能從驗證規則中獲得好處。