实体框架服务层更新POCO

时间:2011-04-22 17:02:27

标签: entity-framework repository-pattern poco service-layer

我正在使用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对象完全相同的属性?你是否必须为你不想展示的每个项目制作隐藏字段,以便它们可以坚持下去?

如何处理将对象保存回数据库?如果您的视图/模型仅处理对象上的几个字段会发生什么?

3 个答案:

答案 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中的所有字段都将被修改。如果您只想修改单个字段,则仍需要正确填写其他字段,否则您的数据库记录将被破坏。

有一种方法可以明确定义哪些字段已更改。您将为每个属性而不是整个实体设置修改后的状态。在通用方法上解决这个问题有点困难,但我试图为EFv4EFv4.1展示一些方法。

答案 2 :(得分:1)

我同意@AbdouMoumen,在视图级别使用模型实体要简单得多。服务层应提供API以在数据存储(db)中保留这些实体。服务层不应该愚蠢地复制存储库律师(即:为每个实体保存(实体)),而是为实体聚合提供高级别保存。例如,您可以在服务层中使用保存(订单),这样可以更新更多基本实体,如库存,客户,帐户。