1. 程式人生 > >Entity Framework 4.1 之四:複雜型別

Entity Framework 4.1 之四:複雜型別

原文名稱:Entity Framework 4.1: Complex Types (4)

預設情況下,EF4.1 將類對映到表,這是約定,但是有時候,我們需要模型比表的粒度更細一些。

地址是一個典型的例子,看一下下面的客戶類。

publicclass Client
{
publicint ClientID { get; set; }
[Required]
[StringLength(
32, MinimumLength=2)]
publicstring ClientName { get; set; }
public Address ResidentialAddress {
get; set; }
public Address DeliveryAddress { get; set; }
}

publicclass Address
{
[Required]
publicint StreetNumber { get; set; }
[Required]
[StringLength(
32, MinimumLength=2)]
publicstring StreetName { get; set; }
}

我們不希望其中的兩個地址屬性都對映到地址表中的記錄,而是讓 EF4.1 都對映到一張表中,將地址展開,如何做到呢?可以通過複雜型別。

像我們前面看到的,我們總是通過標籤或者模型構建器來覆蓋預設約定。我提到過,當我們豐富業務模型的時候,例如必填項,我建議使用屬性。現在我考慮將類中的複雜屬性對映到表中的欄位,所以這裡不是用標籤,而是使用模型構建器。

protectedoverridevoid OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);

modelBuilder.Entity
<Client>().Property(x => x.ClientID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.ComplexType
<Address>();
modelBuilder.Entity
<Client>().Property(i => i.ResidentialAddress.StreetNumber).HasColumnName("ResStreetNumber");
modelBuilder.Entity
<Client>().Property(i => i.ResidentialAddress.StreetName).HasColumnName("ResStreetName");
modelBuilder.Entity
<Client>().Property(i => i.DeliveryAddress.StreetNumber).HasColumnName("DelStreetNumber");
modelBuilder.Entity
<Client>().Property(i => i.DeliveryAddress.StreetName).HasColumnName("DelStreetName");

}

首先,我指定 client-id 作為自動增長的標識列。然後,指定 Address 是複雜型別。如果願意的話,也可以將 [ComplexType] 標籤加到類上來說明。然後,使用 Lambda 表示式將每一個子屬性對映到列上,這將會生成如下的表。

現在,可以使用模型了。

using (var context1 =new MyDomainContext())
{
var client
=new Client
{
ClientName
="Joe",
ResidentialAddress
=new Address
{
StreetNumber
=15,
StreetName
="Oxford"
},
DeliveryAddress
=new Address
{
StreetNumber
=514,
StreetName
="Nolif"
}
};
context1.Clients.Add(client);

context1.SaveChanges();
}
using (var context2 =new MyDomainContext())
{
var clients
= from w in context2.Clients
where w.ClientName =="Joe"
select w;

foreach (var client in clients)
{
Console.WriteLine(
"client residential StreetNumber: "+ client.ResidentialAddress.StreetNumber);
Console.WriteLine(
"client residential StreetName: "+ client.ResidentialAddress.StreetName);
Console.WriteLine(
"client delivery StreetNumber: "+ client.DeliveryAddress.StreetNumber);
Console.WriteLine(
"client delivery StreetName: "+ client.DeliveryAddress.StreetName);
}
}

對於複雜型別,最值得注意的是空的管理。即使複雜型別的所有屬性都是可空的,你也不能將整個複雜型別的物件設為 null, 例如,在這種情況下,即使街道的名稱和街道的號碼不是必填的,也不能有一個住宅的地址為 null,需要建立一個所有屬性都是 null 的地址物件來表示。同樣的道理,當你獲取一個實體的時候,即使所有的屬性都是 null ,EF4.1 也將會建立一個複雜型別的物件。