我在阅读有关实体框架4.0,我想知道为什么我应该创建一个复杂的类型,而不是一个新的实体(表)和它们之间的关系?实体框架复杂类型vs创建新实体
回答
完美的例子是一个地址。使用复杂类型的地址比新实体更容易处理。对于复杂类型,您不必处理主键。考虑访问地址有多少种常见类型的实体会有地址(业务单位,人员,地点)。想象一下,填充许多人的地址并需要为每个人设置一个密钥。对于复杂的类型,只需访问它们的内部属性即可完成。这是一个示例的MSDN链接。 http://msdn.microsoft.com/en-us/library/bb738613.aspx
基于域驱动设计概念,聚合根可以有一个或多个内部对象作为其部分。在这种情况下,内部对象 - 在Aggregate Root的边界内 - 没有任何KEY。父键将应用于它们或以某种方式如此。您的答案返回到保持聚合根内所有零件的好处,使您的模型更健壮,更简单。
聚合根可能包含具有密钥的实体。他们只属于一个聚合根。 – 2015-03-28 11:18:54
这个问题已经出现了一段时间了,但我仍然会添加一个答案,希望随之而来的下一个可怜的哭泣知道他在做什么。
复杂类型不支持延迟加载,至少在EF 4.3中不支持延迟加载。我们以地址情况为例。你有一个有15列的Person表,其中5个包含某些个人的地址信息。它有5万条记录。您为具有复杂类型Address的表创建实体Person。
如果您需要在数据库中的所有个人的名单,你会做
var records = context.Persons;
其中还包括地址,抽5个* 50K值到你的列表中没有任何理由,并用明显的延迟。你可以选择只加载您在一个匿名类型需要
var records = from p in context.Persons
select new {
LastName = p.LastName,
FirstName = p.FirstName,
}
这对于这种情况下行之有效的值,但是如果你需要使用,也就是说,8个非地址栏一个更全面的列表,你要么需要在匿名类型中添加每一个,或只是与第一个案例一起,并返回加载无用的地址数据。
这是关于匿名类型的事情:虽然它们在单个方法中非常有用,但它们强制您在类或子类的其他地方使用动态变量,这会取消Visual Studio的某些重构工具并让您打开运行时间错误。理想情况下,您希望在您的方法中分发实体,以便这些实体尽可能少地携带行李。这就是为什么懒加载非常重要。
说到上面的例子,地址信息应该真正在它自己的表中,并且有一个完整的实体覆盖它。作为一个附带好处,如果您的客户要求第二个人的地址,您可以通过在Person中添加额外的地址引用将其添加到您的模型中。
如果不像上面的例子,你几乎在每个查询中都需要地址数据,并且真的想在Person表中有这些字段,那么只需将它们添加到Person实体即可。你将不再拥有整洁的地址前缀,但它不完全是失去睡眠的东西。
但是等等,还有更多!
复杂类型是一种特殊情况,是普通EF实体平滑景观中的颠簸。你项目中的那些人可能没有资格从你的实体基类继承,这使得他们不可能通过处理你的实体的方法来处理它们。
假设您有一个名为EntityModel的实体基类,它定义了一个属性ID。这是你的所有实体对象的关键,所以您现在可以创建
class EntityModelComparer<T> : IEqualityComparer<T> where T : EntityModel
,你可以再从类型T的任何IQueryable的其中T是实体类鲜明的()来过滤重复使用。复合类型不能从EntityModel继承,因为它没有ID属性,但这很好,因为无论如何你都不会使用独特的。
更进一步,您遇到了一种情况,您需要某种方式来通过任何实体并执行操作。也许你想要在UI上动态列出一个实体的属性,并让用户对它们执行查询。所以你构建一个类可以实例化的特定类型,并将它采取了整个事情的护理:
public class GenericModelFilter<T> : where T : EntityModel
哦,等一下,你的复杂类型的类型EntityModel的不是。现在,您必须将实体继承树复杂化以适应复杂类型或摆脱EntityModel合同并降低可见性。
一起移动,添加,基于用户选择你的类中的方法可以创建,你可以使用LINQ用于过滤任何实体类
Expression<Func<T, bool>> GetPredicate() { ... }
所以现在你可以做这样的事情的表达式:
personFilter = new GenericModelFilter<Person>();
companyFilter = new GenericModelFilter<Company>();
addressFilter = new GenericModelFilter<Address>(); //Complex type for Person
...
var query = from p in context.Persons.Where(personFilter.GetPredicate())
join c in context.Companies.Where(companyFilter.GetPredicate()) on p.CompanyID = c.ID
select p;
这对所有实体对象都是一样的......除了有特殊需求的地址。你不能像对待公司一样为它加入。你可以从Person导航到它,但是你如何将它应用到它上面,最后还是Person?现在你必须花点时间想出一个简单的系统,这个系统在其他地方很容易运行。
该模式在项目的整个生命周期中都会重复出现。我是否根据经验说话?我希望我没有。复杂的类型会阻止你的进步,就像班级背后的一个行为不端的学生一样,不会增加任何内容。自己帮忙,选择实际的实体对象。
- 1. 实体框架:存储复杂类型
- 2. 实体框架EF4复杂类型
- 3. 实体框架5复杂类型
- 4. 实体框架 - 重用复杂类型
- 5. 实体框架5.0复杂类型
- 6. 实体框架中的复杂类型
- 7. 实体框架5种复杂类型
- 8. 实体框架嵌套复杂类型
- 9. 实体框架创建重复实体
- 10. 实体框架重新创建POCO类
- 11. 如何获取实体框架来更新复杂类型?
- 12. 使用实体框架更新复杂数据实体
- 13. ADO.NET实体框架 - 轻松重新创建实体类?
- 14. 实体框架4.0。实体创建
- 15. 实体框架 - 自动生成vs手动创建实体
- 16. 实体框架 - 如何为实体类创建基类?
- 17. 实体框架无法正确创建从MySql存储的复杂类型
- 18. 实体框架不为我的存储过程创建复杂类型?
- 19. 创建复合关键实体框架
- 20. 实体框架5:创建
- 21. 复杂的实体框架加入
- 22. 复杂的实体框架查询
- 23. 实体框架4.1复杂POCOs
- 24. 实体框架的复杂关系
- 25. 实体框架中的复杂继承
- 26. 实体框架 - 删除复杂对象
- 27. 实体框架复杂LINQ支持
- 28. 复杂的实体框架查询
- 29. 复杂Sql的实体框架查询
- 30. 实体框架复杂查询
拥有复杂类型而不是普通标量属性有什么好处? – emzero 2010-04-29 01:01:10
@emzero我猜他们很多,这基本上是一个OOD。您可能不想在发送货件时在地址上定义get方法或将地址对象传递给某些其他方法。它也遵循DRY方法。假设你做了一个ToString()覆盖,你只需要为所有具有Address的类执行一次。 – 2012-04-13 15:07:08
这难道不会让所有不同的表的所有地址都难以执行操作吗?如果我想添加地理位置数据,或者清理所有地址格式等?用这张独立的桌子,这不是很容易吗?或者你可以做一些像 repo.ComplexTypes.ToList() – 2013-03-18 08:52:00