我有一个客户端设置 - > WCF - > POCO - > EF4。
说我有一个包含A个实体的列表。 A实体包含其他属性中的大量B实体,默认情况下不加载。当在客户端上执行某个操作时,可能需要知道B实体的列表......
如果我为A实体加载B实体并将它们附加到集合,A实体实际上已更改,我想在保存实体时它还会将这些“新”B实体保存到A实体中吗?
我可以连接一个GetEntityWithAllDetails
函数,但后来我会得到一些我已经拥有的数据,如果有其他我不想加载的集合,那将是一个完全混乱。
问题可以归结为如何在我只有部分POCO开始的时候在客户端重新完成POCO并且想要避免两次加载数据并且仍然能够依靠EF4来正确保存实体?
答案 0 :(得分:0)
欢迎来到n层开发。
这种情况正是许多架构企业级解决方案在层之间使用数据传输对象的原因。
我建议避免从服务(业务)层到客户端的域实体传播。如果你让实体意识到他们是否已经满载,或者他们目前处于什么级别,那么他们几乎不是“POCO”吗?
所以你写了一个服务方法“GetEntityWithAllDetails”。它应该接受一个GetEntityWithAllDetailsRequest对象并返回一个GetEntityWithAllDetailsResponse对象,该对象包含服务调用者所期望的任何内容,而不再是。
显然,在DTO和域对象之间需要做很多的映射 - 像Automapper(和其他)这样的库可以帮助解决这个问题。
将域实体传播到客户端也会限制您的灵活性与实体的延迟或急切加载,并且您必须处理重新附加/合并实体,这是EF的问题,因为它不会重新附加实体图 - 您必须手动浏览图表。
我会尽力说清楚。将域实体从服务传播到客户端是编程地狱之路,并且很快就会导致对象具有与其目的正交的各种责任。
答案 1 :(得分:0)
这是一项复杂的任务,EF无法处理它 - 这是你的责任。使用分离的实体the change tracking is up to you时。
您的解决方案目前可能是:
听起来很简单,但事实并非如此。在最后一步中,您必须手动向新上下文解释已更改的内容。它通常意味着与ObjectStateManager
(ObjectContext
API)或DbChangeTracker
(如果是DbContext
API)进行大量互动。它还意味着您必须从客户端传递有关更改的信息。
例如,假设您正在修改Order
实体。 Order
实体依赖于Customer
实体,并且它具有从属OrderItem
实体。为了使这个有趣,假设OrderItems必须由不同的仓库处理,因此每个仓库只能访问分配给它的项目。
Order
Order
Customer
而OrderItems
以及OrderItems
的支持。OrderItem
。删除单个OrderItem
因为已停产的产品,并插入另一个Order
以替换已停产的产品。由于供应不足,一些物品将保持不变。仓库将CustomerId
发送回服务器。OrderItem
无法修改。现在你必须明确说明哪个{{1}}已更新(=存在于DB中),未更改(=不需要任何操作),插入(=必须插入)和最差部分被删除(如果你没有从客户端发送一些有关删除的信息,你就无法在不重新编码数据库实体图的情况下知道它。)至少你会很高兴EF不会删除你明确没有标记删除的任何内容。因此,与其他仓库相关的订单项目及其与订单的关系将保持不变。
如何处理它有两种一般方法:
使用DTO而不是直接的EF POCO也有完全独立的架构方法,但它会导致与您目前相同的复杂情况。