保存到DB时出现InvalidOperationException

时间:2013-06-18 08:27:31

标签: c# database linq entity-framework

将帖子添加到我的数据库时遇到问题,这个"添加"从多个线程调用函数。通常在彼此之后很快,我不知道这是否重要,但这就是它的工作方式。

代码:

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" />

还有其他方法可以解决这个问题吗?

1 个答案:

答案 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
  • 开始
  • 对象上下文包括身份映射和变更管理系统;如果你保留的时间超过一次,你就会慢慢积累越来越多的物体;除了导致内存问题之外,这会逐渐降低性能 - 因为每次读取/更新操作现在都有越来越多的数据需要通过
  • 进行

基本上,这里的“修复”是:不要这样做。这不是对象上下文的正确用法。没有应用程序范围的共享对象上下文。