实体框架如何决定是引用现有对象还是创建新对象?

时间:2013-02-04 23:29:40

标签: asp.net asp.net-mvc entity-framework asp.net-mvc-4 entity-framework-5

仅仅因为我的好奇心(以及未来的知识),实体框架5如何决定何时创建新对象而不是引用现有对象?我可能刚刚做错了什么,但似乎我时不时地做一些事情:

using (TestDB db = new TestDB())
{
    var currParent = db.Parents.Where(p => p.Prop == passedProp).FirstOrDefault();
    if(currParent == null) {
         Parent newParent = new Parent();
         newParent.Prop = passedProp;
         currParent = newParent;
    }
    //maybe do something to currParent here
    var currThing = db.Things.Where(t => t.Prop == passedPropTwo).FirstOrDefault();
    currThing.Parent = currParent;
    db.SaveChanges();
}

EF将在数据库中创建一个新的Parent,基本上是currParent的副本,然后将currThing的Parent_ID值设置为该副本。然后,如果我再次这样做(如果已经有两个父母那样),它将不会创建一个新的Parent而是链接到第一个。我真的不明白这种行为,但在玩了一段时间之后就像:

using (TestDB db = new TestDB())
{
    var currParent = db.Parents.Where(p => p.Prop == passedProp).FirstOrDefault();
    if(currParent == null) {
         Parent newParent = new Parent();
         newParent.Prop = passedProp;
         currParent = newParent;
    }
    //maybe do something to currParent here
    var currThing = db.Things.Where(t => t.Prop == passedPropTwo).FirstOrDefault();
    currThing.Parent = db.Parents.Where(p => p.ID == currParent.ID).First();
    db.SaveChanges();
}

似乎解决了这个问题。有什么理由可能会发生这种情况,我应该注意到,或者当时我做这件事的方式有什么奇怪的吗?对不起,我不能更具体地说明确切的代码是什么,我前一段时间遇到过并用上面的代码修复它,所以我没有看到任何理由询问它。更一般地说,EF如何决定是否引用现有项目而不是创建新项目?只是根据ID是否设置?谢谢!

1 个答案:

答案 0 :(得分:2)

如果您的DBContext的特定实例向您提供了该实体的特定实例,那么它将知道它所代表的数据库中的哪些记录,并且您对其所做的任何更改都将适用于该实体。 (那些)记录在数据库中。如果您自己实例化一个新实体,那么您需要告诉DBContext该记录究竟是什么,除非是应该插入数据库的新记录。

在您有多个DBContext个实例的特殊情况下,一个实例为您提供此实体,但您想使用另一个实例来处理并保存实体,那么您必须使用((IObjectContextAdapter)firstDbContext).ObjectContext.Detach()来实现孤立此实体,然后使用((IObjectContextAdapter)secondDbContext).ObjectContext.Parents.Attach()附加它(或ApplyChanges()如果您也正在编辑它 - 这将为您调用Attach

在其他一些特殊情况下(您的对象已被序列化和/或您拥有自我跟踪实体),可能还需要一些额外的步骤,具体取决于您要做的确切内容。


总而言之,如果您的DBContext的特定实例“了解”您的特定实体实例,那么它将与它一起使用,就像它直接绑定到数据库中的特定行一样。 / p>