从我读到的所有内容开始,应该不可能将同一对象附加到不同的dbcontext(并且在这种情况下,我能找到的所有示例和问题都显示出异常)。现在,当我使用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/zh-cn/library/vstudio/ee835846(v=vs.100)。 aspx
public static bool IsProxy(object type)
{
return type != null && ObjectContext.GetObjectType(type.GetType()) != type.GetType();
}
效果很好。
自从Entity Framework引入代码优先样式以来,这已经成为可能,因为您只能使用POCO做到这一点。
的cachedUser
是一个普通的C#类。它没有关于它所附加的上下文的任何信息。同样,新的上下文实例不了解其他上下文的变更跟踪器。因此,无法检查POCO是否已附加到任何地方的上下文中。
当cachedUser
不是POCO而是代理对象时,这种情况会改变。(代理对象是EF动态创建的对象。它从实体类继承,并且包含启用延迟加载并促进更改跟踪的代码和状态)。当您尝试将代理对象附加到第二个上下文时,将出现异常:
IEntityChangeTracker的多个实例不能引用一个实体对象。
这就是为什么在许多情况下建议创建代理而不是POCO的原因。您可以db.Users.Create()
代替使用来创建代理new User()
。
何时创建代理,这是否完全可能以及EF物化代理何时成为超出此问题范围的主题。有关此的更多信息,请参见此处。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句