冠军

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

Entity Framework 4.1 之四:复杂类型

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

原文地址:http://vincentlauzon.wordpress.com/2011/04/13/entity-framework-4-1-complex-types-4/

看到 Entity Framework 4.1 推荐英文教程,为了帮大家看起来方便一些,简单翻译一下。这是一个系列,共有 8 篇,这是第 4 篇。
 
  1. Entity Framework 4.1 之一 : 基础
  2. Entity Framework 4.1 之二 : 覆盖默认的约定
  3. Entity Framework 4.1 之三 : 贪婪加载和延迟加载
  4. Entity Framework 4.1 之四:复杂类型
  5. Entity Framework 4.1 之五:多对多的关系
  6. Entity Framework 4.1 之六:乐观并发
  7. Entity Framework 4.1 之七:继承
  8. Entity Framework 4.1 之八:绕过 EF 查询映射
这篇文章将讨论复杂类型。

默认情况下,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 也将会创建一个复杂类型的对象。

posted on   冠军  阅读(13537)  评论(14编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示