我在将帖子添加到我的数据库时遇到问题,这个“添加”函数是从多个线程调用的。通常彼此很快,我不知道这是否重要,但这就是它的工作方式。
代码:
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 时我得到这个异常:
The changes to the database were committed successfully, but an error occurred while updating the object context. The ObjectContext might be in an inconsistent state. Inner exception message: AcceptChanges cannot continue because the object's key values conflict with another object in the ObjectStateManager. Make sure that the key values are unique before calling AcceptChanges.
我设法找到的所有答案都与您必须添加 StoreGeneratedPattern="Identity"
有关,我已经这样做了,但没有帮助
<Property Name="ID" Type="integer" Nullable="false" StoreGeneratedPattern="Identity" />
那么有没有其他方法可以解决这个问题呢?
最佳答案
最终,在线程之间共享对象上下文是一个非常非常的坏主意。对象上下文旨在用作工作单元 - 即短暂的;典型用法:
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()
如果合适的话)——然后忘掉它;如果您想重新应用您的更改,您可以从一个全新的对象上下文开始 - 对象上下文包括身份映射和变更管理系统;如果你保留它的时间超过一次操作,你就会慢慢地向其中积累越来越多的对象;除了导致内存问题外,这还会逐渐降低性能 - 因为现在每个读取/更新操作都有越来越多的数据需要拖网
基本上,这里的“修复”是:不要那样做。这不是对象上下文的正确用法。没有应用程序范围的共享对象上下文。
关于c# - 保存到数据库时出现 InvalidOperationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17164022/