将断开连接的实体附加到实体框架

时间:2012-02-23 10:35:44

标签: c# entity-framework

这一直困扰着我一段时间。我的问题如下。我有一个类型为 X 的实例,名为 x X 是由Entity Framework生成的实体类。

在我的方法中,我从Web服务接收 x ,因此它没有附加到我的对象上下文,但我知道数据库中已存在具有相同主键的元素,所以我想更新它。我在方法中添加了以下主体,并且工作正常:

objectContext.Xs.Attach(x);
objectContext.ObjectStateManager.ChangeObjectState(x, EntityState.Modified);
objectContext.SaveChanges();

到目前为止一切都很好。但是我的objectContext不是由这个方法创建的,突然这个代码停止工作并抛出一个InvalidOperationException,其中包含以下文字:

  

ObjectStateManager中已存在具有相同键的对象。 ObjectStateManager无法使用相同的键跟踪多个对象。

这是因为在运行此代码之前的某个时间执行了以下代码:

objectContext.Xs.ToList();

这将从数据库中读取所有当前 X 对象,从而将它们添加到ObjectStateManager。

然后我按代码改为:

objectContext.Xs.ApplyCurrentValues(x);
objectContext.SaveChanges();

此工作正常,但如果我再次移除objectContext.Xs.ToList();行,我会收到另一个InvalidOperationException,其中包含以下文字:

  

在ObjectStateManager中找不到具有与提供的对象的键匹配的键的对象。验证提供的对象的键值是否与必须应用更改的对象的键值匹配。

所以现在我遇到了相反的问题。此方法不起作用,因为它由ObjectStateManager跟踪

此外,我还没有找到任何可靠的方法来确定我的 x 是否已被跟踪,所以目前我已经添加了这样的代码:

try
{
    objectContext.Xs.Attach(x);
    objectContext.ObjectStateManager.ChangeObjectState(x, EntityState.Modified);
    objectContext.SaveChanges();
}
catch(InvalidOperationException)
{
    objectContext.Xs.ApplyCurrentValues(x);
}
objectContext.SaveChanges();

这意味着我正在使用异常处理作为正常的程序流(这个元素已经被ObjectStateManager跟踪了,这几乎不例外),我也遇到了一个问题,即我可能会遇到另一个不相关的{{1}我应该以另一种方式处理。

所以我的问题是。有没有人知道一个很好的解决方案,或者至少是一种检查ObjectStateManager是否跟踪 x 的正确方法所以我可以选择其中一种方法而不是try / catch? / p>

1 个答案:

答案 0 :(得分:4)

您需要检查是否已附加具有相同EntityKey的对象。尝试这样的事情:

string containerName = context.DefaultContainerName;
string setName = context.CreateObjectSet<X>().EntitySet.Name;
EntityKey key = new EntityKey(String.Format("{0}.{1}", containerName, setName), 
                              "KeyProperty", x.KeyProperty);
if (context.ObjectStataManager.GetObjectStateEntry(key) != null)
{
    // Apply current values
}
else
{
    // Attach and set state
}