C# 将同一对象附加到实体框架6中的不同上下文
从我读到现在的所有内容来看,不可能将同一个对象附加到不同的DBContext(我能找到的所有示例和问题都显示了这种情况下的例外情况)。现在,当我使用EF6进行测试时,它允许我将同一个对象附加到不同的上下文(来自不同的线程);我甚至可以从一个线程中更改对象,并将其与另一个线程一起保存。 这不一定是一件坏事(除了我必须确保我一直锁定,因为没有抛出异常),只是我想了解发生了什么 有人知道这是否真的是EF6的“新特性”吗 这里有一些代码。从几个不同的线程调用该函数也不例外,如果我在保存之前从另一个线程更改对象,它将使用最后的值:C# 将同一对象附加到实体框架6中的不同上下文,c#,multithreading,entity-framework-6,C#,Multithreading,Entity Framework 6,从我读到现在的所有内容来看,不可能将同一个对象附加到不同的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();
}
编辑
在得到了为什么会发生这种情况的答案后,我还发现了如何检查对象是否为代理:
工作正常。自从Entity Framework引入了代码优先样式以来,这是可能的,因为您只能使用POCO来实现这一点
cachedUser
是一个普通的C类。它没有任何关于它所附加的上下文的信息。另外,一个新的上下文实例根本不知道另一个上下文的更改跟踪程序。因此,无法检查POCO是否连接到任何位置的上下文
当cachedUser
不是POCO而是代理对象时,这种情况会发生变化。(代理对象是EF动态创建的对象。它从entity类继承,包含支持延迟加载和方便更改跟踪的代码和状态)。尝试将代理对象附加到第二个上下文时,会出现异常:
一个实体对象不能被多个IEntityChangeTracker实例引用
这就是为什么在许多情况下建议创建代理而不是POCO的原因。您可以使用db.Users.create()
而不是new User()
来创建代理
何时创建代理,这是否可能,以及何时EF物化代理超出了这个问题的范围。更多信息请访问。谢谢。实际上我是在使用.Find-inside-context来创建我的对象,但我忘记了在我的类中有一个虚拟对象。现在我的对象是proxy,代码抛出错误:-)
public static bool IsProxy(object type)
{
return type != null && ObjectContext.GetObjectType(type.GetType()) != type.GetType();
}