C# 保存到数据库时出现InvalidOperationException
我在向数据库添加帖子时遇到问题,这个“Add”函数是从多个线程调用的。通常很快,我不知道这是否重要,但这就是它的工作方式 代码: 我的问题是,当调用SaveChanges时,会出现以下异常: 已成功提交对数据库的更改,但 更新对象上下文时出错。这个 ObjectContext可能处于不一致的状态。内部异常 消息:AcceptChanges无法继续,因为对象的键 值与ObjectStateManager中的另一个对象冲突。制作 在调用AcceptChanges之前,请确保键值是唯一的 我找到的所有答案都与您必须添加的内容有关,我已经做好了准备,但没有任何帮助C# 保存到数据库时出现InvalidOperationException,c#,database,linq,entity-framework,C#,Database,Linq,Entity Framework,我在向数据库添加帖子时遇到问题,这个“Add”函数是从多个线程调用的。通常很快,我不知道这是否重要,但这就是它的工作方式 代码: 我的问题是,当调用SaveChanges时,会出现以下异常: 已成功提交对数据库的更改,但 更新对象上下文时出错。这个 ObjectContext可能处于不一致的状态。内部异常 消息:AcceptChanges无法继续,因为对象的键 值与ObjectStateManager中的另一个对象冲突。制作 在调用AcceptChanges之前,请确保键值是唯一的 我找到的所有
<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
它可能比某些场景中的情况要复杂一些,例如在页面/请求期间保留对象上下文,但不应在调用方之间共享。原因很多,但基本上所有竞争更新都需要锁定,这里的“更新”包括从数据库读取任何记录或延迟加载属性的简单操作。当被多个线程访问时,对象上下文会变得不稳定,这并不奇怪:这种情况(通常)不受支持
此外,具有长期对象上下文还存在其他问题:
- 有时情况会变糟(例如超时、死锁、回滚,或者只是一个简单的连接错误);在这里,适当的响应方式就是丢弃现在已损坏的对象上下文(
it,如果合适的话)-并忘掉它;如果要重新应用更改,请从新的对象上下文开始Dispose()
- 对象上下文包括身份映射和变更管理系统;如果你将它保存的时间超过一次操作,你会慢慢地将越来越多的物体积累到其中;除了造成内存问题外,这还会逐渐降低性能,因为现在每一次读取/更新操作都需要处理越来越多的数据
基本上,这里的“修正”是:不要这样做。这不是对象上下文的正确用法。没有应用程序范围的共享对象上下文。不一致始终表示进程尚未完全终止ist工作。如果使用多个线程访问数据库,则DBMS必须能够处理此问题,或者必须使代码具有线程安全性。使用多个线程的对象上下文通常意味着发生了非常糟糕的事情—这不是预期的用法,可能会导致非常糟糕的事情。接受异常也是一个非常糟糕的主意。你能详细介绍一下这里的情况吗?这是什么类型的应用程序,为什么它在线程之间共享对象上下文?谢谢!这看起来很有效,如果我这样做,我甚至可以跳过我的锁吗?@Nick3-yes;如果没有共享对象上下文,则没有理由进行同步
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