How does Entity Framework decide whether to reference an existing object or create a new one?

≡放荡痞女 提交于 2019-12-10 15:33:42

问题


Just for my curiosity (and future knowledge), how does Entity Framework 5 decide when to create a new object vs. referencing an existing one? I might have just been doing something wrong, but it seems that every now and then if I do something along the lines of:

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 will create a new Parent in the database, basically a copy of the currParent, and then set the Parent_ID value of currThing to that copy. Then, if I do it again (as in, if there's already two of those parents), it won't make a new Parent and instead link to the first one. I don't really understand this behavior, but after playing around with it for a while something like:

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();
}

seemed to fix the problem. Is there any reason this might happen that I should be aware of, or was there just something weird about the way I was doing it at the time? Sorry I can't be more specific about what the exact code was, I encountered this a while ago and fixed it with the above code so I didn't see any reason to ask about it. More generally, how does EF decide whether to reference an existing item instead of creating a new one? Just based on whether the ID is set or not? Thanks!


回答1:


If your specific instance of your DBContext provided that specific instance of that entity to you, then it will know what record(s) in the database it represents and any changes you make to it will be proper to that(those) record(s) in the database. If you instantiate a new entity yourself, then you need to tell the DBContext what exactly that record is if it's anything but a new record that should be inserted into your database.

In the special scenario where you have multiple DBContext instances and one instance provides you this entity but you want to use another instance to work with and save the entity, then you have to use ((IObjectContextAdapter)firstDbContext).ObjectContext.Detach() to orphan this entity and then use ((IObjectContextAdapter)secondDbContext).ObjectContext.Parents.Attach() to attach it (or ApplyChanges() if you're also editing it - this will call Attach for you).

In some other special scenarios (your object has been serialized and/or you have self-tracking entities), some additional steps may be required, depending on what exactly you are trying to do.


To summarize, if your specific instance of your DBContext is "aware" of your specific instance of an entity, then it will work with it as if it is directly tied to that specific row in the database.



来源:https://stackoverflow.com/questions/14697661/how-does-entity-framework-decide-whether-to-reference-an-existing-object-or-crea

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!