2012-01-15 90 views
0

我以为我把这一切都弄清楚了,但我正在打砖墙。实体如何轻松更新? (EF代码优先,MVC3)

客户端发送一个对象,我的控制器检查用户是否有权编辑,然后继续更新数据库中的实体。 (以及该对象具有的任何导航属性)。
我的问题是,我似乎无法得到它的工作...

我试图

var obj = context.Recipes.SingleOrDefault(o=>o.ID == id); 
UpdateModel(obj); 

但我得到了一个“模型无法更新”异常。
所以我尝试了不同的方法,把配方R插入参数列表(并让模型绑定做的工作),并调用

context.Recipes.Attach(r); 

,但留下的“不变”的东西,所以context.SaveChanges()什么都不做。

是否有一个简单的解决方案,而不必为我的对象上的EVERY属性编写obj.SomeProperty = r.SomeProperty

奖金的问题:如果我的实体具有导航性能(集合)我明明添加在(与ID == 0)所发出的新的,但我怎么知道删除哪一个?我可以在这里利用EF的变更跟踪吗?

对于这两个问题:应该有一个神奇的“比较此对象与此对象,然后保存”的方法?

+0

这两个代码片段是如何相关的?你的问题看起来有点不一致。如果仅使用第一个片段并调用“SaveChanges”,会发生什么? – 2012-01-15 11:35:55

+0

例外。 “模型不能更新”。 – TDaver 2012-01-15 11:46:00

+0

是否有任何异常的细节?如果您使用急切加载来加载所有必须更新的关系,会发生什么情况? – 2012-01-15 12:19:59

回答

3

回答你的问题是非常不受欢迎。 EF对此没有任何支持。 EF只能同步没有导航属性的简单对象的状态。一旦必须同步关系中的更改(如添加或删除相关实体),您必须执行此操作completely manually - 特别是删除需要此操作,或者必须将已删除的关系设置为与客户端分开的集合,并在附加实体上复制删除操作,这非常麻烦。

作为workaround人们使用MVC中的TryUpdateModelUpdateModel执行导航属性的更改,但在这种情况下,您不能对更新过程提出任何其他要求。简单的旧值将被来自客户端的新值覆盖。

EF代码首先具有等同于ApplyOriginalValues

context.Entry(attachedEntity).OriginalValues.SetValues(detachedEntity); 
+0

我会继续前进并编写一个'foreach(var p in obj.GetType()。GetProperties())'code ... – TDaver 2012-01-15 13:04:39

1

尝试到位更新模型像下面的使用EntityState,看看它是否有助于

context.Entry(obj).State = EntityState.Modified; 
db.SaveChanges(); 
+0

半伟大。有一些属性(如“创建”)不需要更新。 CodeFirst中是否有类似“ApplyOriginalValues”的方法?这会有帮助吗? – TDaver 2012-01-15 11:45:39

+0

我不确定是否有像dat这样的东西......有一件事你可以在这方面做......虽然通过调用'var originalItem = yourContext.YourModel.Find(id)'来加载原始对象,然后替换通过使用'modifiedObj.Created = originalItem.Created' ....等字段的值的值,并最后调用EntityState.Modified – 2012-01-15 12:00:04

+0

我无法加载对象,而我试图附加另一个副本该实体的上下文。这是一个例外。 :( – TDaver 2012-01-15 13:03:53