在Entity Framework中如何正确地将记录对象附加到数据上下文?

问题描述:

我需要为某些记录切换数据上下文。所以基本上我有db上下文A和B,我使用A获取记录,然后我切换到B,更改记录并保存。

I need to switch data context for some records. So basically I have db context A and B, I fetch records using A, then I switch to B, alter records, and save them.

当我调用Attach for B ,我得到异常,记录正在使用多个数据上下文,当我添加Detach for A,我得到异常,记录不附加到A。

When I call Attach for B, I get exception that records are using by multiple data context, when I add Detach for A, I get exception, that records are not attached to A.

那么如何我切换数据上下文?

So how can I switch the data context?

db_creator 是数据库上下文的创建者。在这里我获取数据(更正版本):

db_creator is creator of db context. Here I fetch the data (corrected version):

using (var db = db_creator.Create())
{
  var coll = db.Mailing.Where(it => !it.mail_IsSent).ToList(); // (*)
  coll.ForEach(it => db.Detach(it));
  return coll;
}

(*)错误是由重构这一块造成的,我创建了额外的数据上下文,然后我试图从另一个分离记录。

(*) the mistake was caused by refactoring this piece, I created extra data context, and then later I tried to detach records from another one.

现在我想将数据上下文切换到新的一个,做一些计算和修改并保存记录。 coll 列表的记录:

Now I would like to switch data context to new one, do some computation and modifications and save the records. coll is List of the records:

using (var db = db_creator.Create())
{
  coll.ForEach(it => db.Mailing.Attach(it));
  ...
  db.SaveChanges();
}


我建议您更改您的设计和一次有一个上下文。 (根据您的项目类型,这可能会有所不同,通常在网络应用程序中,每个http请求都是一个上下文。)

I recommend change your design and have ONE context at a time. (Based on your project type this could vary. Usually in web apps it's one context per http request.)

例如,在Web应用程序中,您可以像下面这样做:

For example in a web application, you can do this like below:

protected MyContext Context
{
    get
    {
        var context = HttpContext.Current.Items["MyContext"];
        if (context == null)
        {
            context = new MyContext();
            HttpContext.Current.Items.Add("MyContext", context);
        }
        return context as MyContext;
    }
}  

并将其处理在您的Application_EndRequest中:

And dispose it in your Application_EndRequest:

app.EndRequest += (sender, args) =>
{
    HttpContext.Current.Items.Remove("MyContext");
}

如果您有多个项目类型,请考虑使用Ioc。

但是如果你还想使用两个上下文,你可以按照下面的方式( myEntity 是你要分离/附加的对象):

If you have multiple project types, then consider using an Ioc.
But if you still want to use two contexts, you can do as below(myEntity is your object you want to detach/attach):

if (context1.Entry(myEntity).State != EntityState.Detached);
{
    ((IObjectContextAdapter)context1).ObjectContext.Detach(myEntity);
}
context2.MyEntities.Attach(myEntity);