将 POCO 中的当前值应用到 DynamicProxy 会在复杂对象上出现错误
我有一个 MVC3 项目,它使用 EF4 项目作为其域。 Domain 是一个模型优先项目,使用 T4 构建 POCO 对象。 域中有多种复杂类型在发挥作用,只要我使用 context.CreateObject() 返回的代理,一切都会很好。
当调用 MVC3 操作时,模型绑定器会传递一个非代理对象,其中包含要应用于域的更改。
我想使用“代理”原始版本,以便视图稍后可以访问导航属性,因此直接的 AttachTo 不会削减它。
我需要首先从上下文中获取“原始”代理对象,然后使用模型绑定器提供的 POCO 中包含的更改来更新它。
根据我所读到的内容以及我的研究告诉我,我应该能够使用类似以下内容来完成此操作:
public static T GetUpdatedProxy<T>(this ObjectContext context, string entitySetName, T entity)
where T : class
{
object original; // db original POCO, proxy wrapped.
var entityKey = context.CreateEntityKey(entitySetName, entity);
//Load DB object
context.GetObjectByKey(entityKey, out original)
//Apply changes from binder supplied POCO object.
context.ApplyCurrentValues<T>(entitySetName, entity); //<= error here
return (T) original;
}
我的问题是这个错误:
[InvalidOperationException: The entity of type 'System.Data.Entity.DynamicProxies.Value_E954C24C522BA1D4124F434A57391656EFA4DD7CEFFD3A5CE35FC1532CD1B10A' references the same complex object of type 'Domain.DateRange' more than once. Complex objects cannot be referenced multiple times by the same entity.]
System.Data.Objects.EntityEntry.CheckForDuplicateComplexObjects(Object complexObject) +418
System.Data.Objects.EntityEntry.DetectChangesInProperties(Boolean detectOnlyComplexProperties) +211
System.Data.Objects.Internal.EntityWithChangeTrackerStrategy.UpdateCurrentValueRecord(Object value, EntityEntry entry) +93
System.Data.Objects.Internal.EntityWrapper`1.UpdateCurrentValueRecord(Object value, EntityEntry entry) +17
System.Data.Objects.EntityEntry.ApplyCurrentValuesInternal(IEntityWrapper wrappedCurrentEntity) +107
System.Data.Objects.ObjectContext.ApplyCurrentValues(String entitySetName, TEntity currentEntity) +365
- 非代理对象上的复杂对象和非代理对象上的复杂对象 代理对象不一样。
- 该实体只有一个复杂对象,因此不能多次设置它,即同一 ComplexType 的两个属性。
- 复杂对象本身实际上没有设置任何值,因此两个可为空的字段实际上仍然为空。
- 如果我确实使用 AttachTo 方法,然后设置对象状态来修改保存工作,但我以后无法使用该对象返回视图,因为导航属性为 null。
有什么想法吗?我很感激你的帮助。
I have an MVC3 project that is using an EF4 project as its Domain.
The Domain is a Model first project that uses T4 to build POCO objects.
There are several ComplexTypes at play in the Domain and everything works great as long as I use the proxies returned by context.CreateObject().
When an MVC3 action is called, the model binder passes a non-proxy object that contains the changes to be applied to the Domain.
I want to work with the "proxy'ed" original so the views have access to navigation properties later, so a straight up AttachTo doesn't cut it.
I need to get the "original" proxy'ed object from the context first, then update it with the changes contained in the POCO provided by the model binder.
From what I've read, and my research tells me, I should be able to accomplish this using something like the following:
public static T GetUpdatedProxy<T>(this ObjectContext context, string entitySetName, T entity)
where T : class
{
object original; // db original POCO, proxy wrapped.
var entityKey = context.CreateEntityKey(entitySetName, entity);
//Load DB object
context.GetObjectByKey(entityKey, out original)
//Apply changes from binder supplied POCO object.
context.ApplyCurrentValues<T>(entitySetName, entity); //<= error here
return (T) original;
}
My issue is this error:
[InvalidOperationException: The entity of type 'System.Data.Entity.DynamicProxies.Value_E954C24C522BA1D4124F434A57391656EFA4DD7CEFFD3A5CE35FC1532CD1B10A' references the same complex object of type 'Domain.DateRange' more than once. Complex objects cannot be referenced multiple times by the same entity.]
System.Data.Objects.EntityEntry.CheckForDuplicateComplexObjects(Object complexObject) +418
System.Data.Objects.EntityEntry.DetectChangesInProperties(Boolean detectOnlyComplexProperties) +211
System.Data.Objects.Internal.EntityWithChangeTrackerStrategy.UpdateCurrentValueRecord(Object value, EntityEntry entry) +93
System.Data.Objects.Internal.EntityWrapper`1.UpdateCurrentValueRecord(Object value, EntityEntry entry) +17
System.Data.Objects.EntityEntry.ApplyCurrentValuesInternal(IEntityWrapper wrappedCurrentEntity) +107
System.Data.Objects.ObjectContext.ApplyCurrentValues(String entitySetName, TEntity currentEntity) +365
- The complex object on the non-proxy object and the one on the
proxy'ed object are not the same. - The entity only has the one complex object so it can't be set multiple times to say, two properties of the same ComplexType.
- The complex object itself hasn't actually had any values set to it so the two null-able fields are in fact still null.
- If I do use the AttachTo method and then set the object state to modified the save works but I can't later use the object to return a view because the navigation properties are null.
Any thoughts? I appreciate the help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我终于想出了一个解决方法。
我绝对无法让 context.ApplyCurrentValues() 从 POCO 工作到代理。
我提出的解决方案是从 IOC CreateObject() 方法创建一个新代理,使用反射来迭代并复制 POCO 上的属性,然后使用该代理调用 AttachTo()。
我尝试迭代并将属性从 context.TryGetObjectByKey(entityKey, out getObject) 复制到预加载的代理,但当我尝试保存上下文时,它会给我一个关于复杂对象为空(实际上不是)的不同错误。
我在 t4 模板中添加了一个可克隆的接口及其对 ComplexTypes 的实现:
SetValueOf 和 GetValueOf 是我用于提高可读性的简单扩展方法:
I finally figured out a workaround.
I was absolutely unable to get context.ApplyCurrentValues() to work from a POCO to a Proxy.
The solution I came up with was to create a new proxy from the IOC CreateObject() method, use reflection to iterate over and copy the properties on the POCO, then call AttachTo() with the proxy.
I tried to iterate and copy the properties to a preloaded proxy from context.TryGetObjectByKey(entityKey, out getObject) but it would give me a different error about the complex object being null (which it wasn't) when I tried to save the context.
I added a Clone-able interface and it's implementations to ComplexTypes in the t4 template:
SetValueOf and GetValueOf are simple Extension Methods I use for readability: