4

只是出于我的好奇心(和未来的知识),Entity Framework 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 值设置为该副本。然后,如果我再做一次(例如,如果已经有两个父母),它不会创建一个新的父母,而是链接到第一个。我不太了解这种行为,但是在玩了一段时间之后,就像:

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?谢谢!

4

1 回答 1

2

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

在您有多个DBContext实例并且一个实例为您提供此实体但您想使用另一个实例来处理和保存该实体的特殊情况下,您必须使用((IObjectContextAdapter)firstDbContext).ObjectContext.Detach()孤立该实体,然后使用((IObjectContextAdapter)secondDbContext).ObjectContext.Parents.Attach()附加它(或者ApplyChanges()如果您'也在编辑它 - 这会要求Attach你)。

在其他一些特殊情况下(您的对象已被序列化和/或您有自跟踪实体),可能需要一些额外的步骤,具体取决于您要执行的操作。


总而言之,如果您的特定实例DBContext“知道”您的特定实体实例,那么它将与它一起工作,就好像它直接绑定到数据库中的特定行一样。

于 2013-02-04T23:57:27.130 回答