c# - 保存到数据库时出现 InvalidOperationException

标签 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 时我得到这个异常:

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/

相关文章:

c# - 找不到适合实体类型字符串的构造函数

在 Windows Azure 上发布后未创建数据库

mysql - 缓慢的 MySQL SELECT 性能

python - 运行每日 SQL 查询和通过电子邮件发送结果的最佳方法

c# - 使用 LINQ 将集合拆分为 `n` 部分?

c# - Windows Phone 7 隐藏应用程序栏

c# - 适用于 Windows Mobile 的 gzip 工具比 SharpZipLib 更好?

c# - 自定义 JSON.net 反序列化为 Dictionary<string, string>

c# - 未从FirstOrDefault公开的可为空的引用类型信息

c# - 在 DataTable 中按日期时间对字符串列进行排序