将帖子添加到我的数据库时遇到问题,这个"添加"从多个线程调用函数。通常在彼此之后很快,我不知道这是否重要,但这就是它的工作方式。
代码:
private object dbLock = new object();
public void Add(string fileName, DateTime collectionTime)
{
try
{
lock (dbLock)
{
var collection = new Collection
{
Filename = fileName,
Datetime = collectionTime,
};
_entities.AddToCollection(collection);
_entities.SaveChanges();
CollectionChanged(collection, null);
}
}
catch (Exception ex)
{
}
finally
{
}
}
我的问题是,当调用SaveChanges时,我得到了这个例外:
数据库的更改已成功提交,但是 更新对象上下文时发生错误。该 ObjectContext可能处于不一致状态。内部异常 消息:AcceptChanges无法继续,因为对象的键 值与ObjectStateManager中的另一个对象冲突。使 确保在调用AcceptChanges之前键值是唯一的。
我设法找到的所有答案都与您必须添加StoreGeneratedPattern="Identity"
有关,我已经这样做了,但它没有帮助
<Property Name="ID" Type="integer" Nullable="false" StoreGeneratedPattern="Identity" />
还有其他方法可以解决这个问题吗?
答案 0 :(得分:3)
最终,在线程之间共享对象上下文是一个真的坏主意。对象上下文旨在用作工作单元 - 即短暂的;典型用法:
using(var ctx = new SomeObjectContextType()) // assuming IDisposable
{
// not shown: get some records, if needed
...
// not shown: update, add, remove some records, if needed
ctx.SaveChanges();
} // and now it is gone, never to be used again
在某些情况下,它可能会比位更复杂,例如在页面/请求的持续时间内保留对象上下文,但它应该不在呼叫者之间共享。原因很多,但基本上所有竞争更新都需要锁定,这里的“更新”包括从数据库读取任何记录或懒惰加载属性的简单行为。当多个线程访问时,对象上下文变得不稳定应该不足为奇:该场景不受(通常)支持。
此外,拥有一个长期存在的对象上下文还存在其他问题:
Dispose()
,如果合适的话) - 并且忘掉它;如果您想重新应用更改,请从 fresh object-context 基本上,这里的“修复”是:不要这样做。这不是对象上下文的正确用法。没有应用程序范围的共享对象上下文。