将断开连接的实体附加到实体框架
本文关键字:实体 框架 连接 断开 | 更新日期: 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
}