我正在使用Service Layer --> Repository --> Entity Framework (Code-First) w/POCO objects
方法,而且我很难更新实体。
我正在使用AutoMapper将我的域对象映射到我的View模型,这对于获取数据非常有用,我怎么不将这些更改重新发送回数据库?
使用纯POCO对象,我会假设没有任何类型的更改跟踪,所以我看到我唯一的选择就是自己处理它。您是否确保您的View Models具有与Domain Objects完全相同的属性?如果我只在视图模型上更改一个或两个字段怎么办?域对象上的其余字段是否会被默认值覆盖在数据库中?
话虽如此,最好的方法是什么?
谢谢!
修改
所以我绊倒的是这个,让我们举一个简单的Customer
:
1)Controller
有一项服务CustomerService
,可以调用服务GetCustmoerByID
方法。
2)Service
调用CustomerRepository
并检索Customer
对象。
3)Controller
使用AutoMapper将Customer
映射到ViewModel
。
4)Controller
将模型交给View
。一切都很棒!
现在,在视图中,您对客户进行了一些修改,并将其发布回控制器,以便将更改保留到数据库中。
我认为此时对象已分离。那么模型是否应该具有与Customer
对象完全相同的属性?你是否必须为你不想展示的每个项目制作隐藏字段,以便它们可以坚持下去?
如何处理将对象保存回数据库?如果您的视图/模型仅处理对象上的几个字段会发生什么?
答案 0 :(得分:5)
如果您正在使用EF Code First,即:DbContext API,那么您仍然可以使用由上下文类处理的更改跟踪。
对对象进行更改后,您只需在上下文中调用SaveChanges()
即可将更改保留在数据库中。
修改强>:
由于您使用AutoMapper创建实体的“副本”,因此它不再附加到您的上下文。
我猜你可以做的是类似于你在ASP.NET MVC中使用的内容(使用UpdateModel
)。您可以从上下文中获取原始实体,获取ViewModel(可能包含已更改的属性)并手动更新旧实体(仅修改属性)或使用AutoMapper。然后使用context.SaveChanges()
保留更改。
另一种解决方案是将模型实体作为ViewModel的[部分]发送。这样,您就可以将实体附加到容器中,并且更改跟踪仍然有效。
希望这会有所帮助:)
答案 1 :(得分:3)
对于使用分离对象,您完全正确,您负责通知上下文中有关已分离实体的更改。
基本方法是将实体设置为已修改。这适用于标量和复杂属性,但它不适用于导航属性(FK关系除外) - 为了进一步阅读导航属性问题,请检查this answer(它与EFv4和ObjectContext API有关,但同样的问题是DbContext API)。这种方法的缺点是DB中的所有字段都将被修改。如果您只想修改单个字段,则仍需要正确填写其他字段,否则您的数据库记录将被破坏。
有一种方法可以明确定义哪些字段已更改。您将为每个属性而不是整个实体设置修改后的状态。在通用方法上解决这个问题有点困难,但我试图为EFv4和EFv4.1展示一些方法。
答案 2 :(得分:1)
我同意@AbdouMoumen,在视图级别使用模型实体要简单得多。服务层应提供API以在数据存储(db)中保留这些实体。服务层不应该愚蠢地复制存储库律师(即:为每个实体保存(实体)),而是为实体聚合提供高级别保存。例如,您可以在服务层中使用保存(订单),这样可以更新更多基本实体,如库存,客户,帐户。