这一直困扰着我一段时间。我的问题如下。我有一个类型为 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>
答案 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
}