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

本文关键字:实体 框架 连接 断开 | 更新日期: 2023-09-27 18:25:28

这已经困扰我一段时间了。我的问题如下。我有一个X类型的实例,称为XX是由实体框架生成的实体类。

在我的方法中,我从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已经跟踪了该元素,这并不奇怪),而且我还遇到了一个问题,即我可能会捕获另一个本应以另一种方式处理的不相关的InvalidOperationException

所以我的问题是。有人知道一个好的解决方案吗?或者至少知道一个正确的方法来检查ObjectStateManager是否跟踪了x,这样我就可以根据它选择一种方法,而不是try/catch?

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

您需要检查是否已附加具有相同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
}