Entity Framework如何决定是引用现有对象还是创建新对象? [英] How does Entity Framework decide whether to reference an existing object or create a new one?

查看:93
本文介绍了Entity Framework如何决定是引用现有对象还是创建新对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了我的好奇心(和未来的知识),Entity Framework 5如何决定什么时候创建一个新对象,而不是引用现有的对象?我可能刚刚做错了事情,但似乎每一次,如果我按照以下方式做某事:

 使用(TestDB db = new TestDB())
{
var currParent = db.Parents.Where(p => p.Prop == passedProp).FirstOrDefault();
if(currParent == null){
父newParent = new Parent();
newParent.Prop = passedProp;
currParent = newParent;
}
//可能做某事currParent这里
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){
父newParent = new Parent();
newParent.Prop = passedProp;
currParent = newParent;
}
//可能做某事currParent这里
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是否设置?谢谢!

解决方案

如果您的具体实例 DBContext 那么该实体的实例就会知道它所代表的数据库中的哪些记录,并且对它做出的任何更改对于数据库中的那些记录将是适当的。如果您自己实例化一个新实体,那么您需要告诉 DBContext 该记录是什么,如果它只是一个新的记录,应该插入到您的数据库中。 p>

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



在其他一些特殊情况(您的对象已经序列化和/或者您有自我跟踪实体),可能需要一些额外的步骤,具体取决于您正在尝试做什么。






总结arize,如果你的 DBContext 的具体实例是感知一个实体的特定实例,那么它将与它一起工作,就好像它直接绑定到该特定行在数据库中。


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!

解决方案

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.

这篇关于Entity Framework如何决定是引用现有对象还是创建新对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆