[英]Attach same object to different contexts in Entity Framework 6
从我读到的所有内容到现在,不应该将相同的对象附加到不同的dbcontexts(我可以找到的所有示例和问题都在这种情况下显示异常)。 现在,当我使用EF6进行测试时,它允许我将相同的对象附加到不同的上下文(来自不同的线程); 我甚至能够从一个线程更改对象并将其与另一个线程一起保存。 这不一定是坏事(除了事实我必须确保我一直锁定,因为没有抛出异常),只是我想了解发生了什么。
有人知道这是否真的是EF6中的“新功能”?
一些代码在这里。 从几个不同的线程调用它没有异常,如果我在保存之前从另一个线程更改对象,它将采用最后的值:
using (var db = new TestContext())
{
db.Users.Attach(_cachedUser);
MessageBox.Show("attached"); //I use this to pause the thread as long as I want
_cachedUser.UserCode = tbCode.Text;
_cachedUser.UserDesc = tbDesc.Text;
MessageBox.Show("ready to save"); //pause again
db.SaveChanges();
}
编辑收到答案为什么会发生这种情况后,我还发现了如何检查对象是否是代理: http : //msdn.microsoft.com/en-us/library/vstudio/ee835846(v = vs.100)。 ASPX
public static bool IsProxy(object type)
{
return type != null && ObjectContext.GetObjectType(type.GetType()) != type.GetType();
}
工作得很好。
这是可能的,因为实体框架引入了代码优先的样式,因为您只能使用POCO执行此操作。
cachedUser
是一个普通的C#类。 它没有关于它附加的上下文的任何信息。 此外,新的上下文实例不了解另一个上下文的更改跟踪器。 所以没有办法检查POCO是否附加到任何地方的上下文。
当cachedUser
不是POCO而是代理对象时,这会发生变化。 (代理对象是EF在运行中创建的对象。它继承自实体类,它包含启用延迟加载和促进更改跟踪的代码和状态)。 当您尝试将代理对象附加到第二个上下文时,您将收到异常:
IEntityChangeTracker的多个实例不能引用实体对象。
这就是为什么在许多情况下,建议创建代理而不是POCO。 您可以使用db.Users.Create()
代替new User()
来创建代理。
什么时候创建代理,这是否可行以及何时EF物化代理是一个超出此问题范围的主题。 有关这方面的更多信息,请点击此处
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.