C# 将同一对象附加到实体框架6中的不同上下文

C# 将同一对象附加到实体框架6中的不同上下文,c#,multithreading,entity-framework-6,C#,Multithreading,Entity Framework 6,从我读到现在的所有内容来看,不可能将同一个对象附加到不同的DBContext(我能找到的所有示例和问题都显示了这种情况下的例外情况)。现在,当我使用EF6进行测试时,它允许我将同一个对象附加到不同的上下文(来自不同的线程);我甚至可以从一个线程中更改对象,并将其与另一个线程一起保存。 这不一定是一件坏事(除了我必须确保我一直锁定,因为没有抛出异常),只是我想了解发生了什么 有人知道这是否真的是EF6的“新特性”吗 这里有一些代码。从几个不同的线程调用该函数也不例外,如果我在保存之前从另一个线程更

从我读到现在的所有内容来看,不可能将同一个对象附加到不同的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();
}