【问题标题】:InvalidOperationException when calling SaveChanges in .NET Entity framework在 .NET 实体框架中调用 SaveChanges 时出现 InvalidOperationException
【发布时间】:2009-06-17 17:48:20
【问题描述】:

我正在尝试学习如何使用 Entity 框架,但遇到了一个我无法解决的问题。 我正在做的是浏览我拥有的电影列表并将每一部插入一个简单的数据库中。

这是我正在使用的代码

private void AddMovies(DirectoryInfo dir)
{
    MovieEntities db = new MovieEntities();
    foreach (DirectoryInfo d in dir.GetDirectories())
    {
        Movie m = new Movie { Name = d.Name, Path = dir.FullName };
        db.AddToMovies(movie);
    }
    db.SaveChanges();
}

当我这样做时,我在读取的 db.SaveChanges() 处得到一个异常。

对数据库的更改是 提交成功,但报错 更新对象时发生 语境。 ObjectContext 可能在 不一致的状态。内部异常 消息:AcceptChanges 无法继续 因为对象的键值 与另一个对象冲突 对象状态管理器。确保 键值在调用之前是唯一的 接受更改。

我无法找出导致此问题的原因。 我的数据库表包含三列
Id int 自动增量
名称 nchar(255)
路径 nchar(255)

更新: 我检查了我的 edmx 文件,SSDL 部分具有建议的 StoreGeneratedPattern="Identity" 。我还关注了博客文章,并尝试按照那里的建议在 CSDL 中添加 ClientAutoGenerated="true" 和 StoreGenerated="true"。这导致了编译错误(错误 5:不允许使用“ClientAutoGenerated”属性。)。由于这篇博文来自 2006 年,并且它有一个指向后续帖子的链接,我认为它已被更改。

但是,我无法阅读后续帖子,因为它似乎需要一个 msdn 帐户。

【问题讨论】:

  • 我的答案是在属性see here for more details 上设置StoreGeneratedPattern="Identity"
  • 当您对 INSERT、UPDATE、DELETE 使用 SotredProcedure 映射并且您的 ID 密钥是 SP 内的计算密钥时,也会发生这种情况。

标签: c# .net entity-framework


【解决方案1】:

我找到了解决办法。

发生的情况是,当我创建表时,我忘记添加主键并将 (Is Identity) 属性设置为 yes。然后我创建了我的实体模型并得到了这个错误。

我回去修复了我的数据库表,但我仍然遇到了奇怪的异常。最终解决问题的方法是删除实体并在表修复后重新创建它。

没有更多的例外:)

【讨论】:

    【解决方案2】:

    上次我尝试了以下代码,我说它工作正常

    bs.SuspendBinding();
    Data.SaveChanges();
    bs.ResumeBinding();
    

    我今天想告诉你的重要事情是:

    1- 如果我们使用上面的代码来暂停绑定,我们必须做更多的代码来修复很多场景,比如集合中的索引丢失和主从绑定

    2- 如果我们使用下面的代码而不是上面的代码,我们将看到异常消失,一切都会好起来的,无需编写更多代码

            Data.SaveChanges(System.Data.Objects.SaveOptions.None);
    

    我希望这能解决你的类似问题

    谢谢朋友们

    【讨论】:

    • 注意:System.Data.Objects.SaveOptions.None 仅在 .Net 4.0 中可用。
    • 它可能只是 .Net 4.0,但 SaveOptions.None 在同样的问题上对我很有用。
    • 我在 EF5 或 6 中使用什么?有没有等效的选项,因为我遇到了类似的问题?谢谢
    【解决方案3】:

    这个异常似乎告诉您在 Id 列中的几行中有相同的值,这应该只有唯一值,因为它是一个键列。 Entity Framework 可以通过两种方式处理此类列:您(客户端)生成唯一值,或者服务器生成唯一值。在您的情况下,允许服务器生成自动递增密钥似乎是合乎逻辑的。

    您的 SSDL 文件中是否为 Id 列设置了 StoreGeneratedPattern 键?

    这是来自this blogpost的示例:

    <EntityType Name="rooms" Key="id">
        <Property Name="id" Type="int" Nullable="false" 
                  StoreGeneratedPattern="Identity" />
        <Property Name="name" Type="nvarchar" Nullable="false" MaxLength="50" />
    </EntityType>
    

    【讨论】:

    • 在 EF4 中是“身份”而不是“身份”
    • 谢谢!过去一周左右,这个问题一直让我发疯。我确实必须手动编辑文件。在属性中更改它只添加了一个注释标记。
    【解决方案4】:
    System.Data.Objects.SaveOptions.None
    

    这解决了问题,但我想知道 uning none 或其他选项之间有什么区别。

    【讨论】:

      【解决方案5】:

      如果你有绑定源绑定,你应该调用suspendbinding:

              bs.SuspendBinding();
              Data.SaveChanges();
              bs.ResumeBinding();
      

      【讨论】:

        【解决方案6】:

        检查您的任何实体中是否缺少主键, 如果是,则创建它们,然后执行“UpdateModel from Database”

        这应该可以解决问题

        【讨论】:

          【解决方案7】:

          同时检查您是否将另一列的“Is Identity”属性设置为“yes”,并且您正在向其中插入重复值。

          【讨论】:

            【解决方案8】:

            我在跨越三个级别的表关系中遇到了类似的问题,例如 Customer->Order->Order-Details 使用 oracle 12C Auto-ID Trigger 来生成密钥。使用SaveChanges() 的插入正在抛出System.InvalidOperationException

            解决方案:增加函数SaveChanges(System.Data.Objects.SaveOptions.None) 防止系统在对象图状态下使用临时EntityKeys 并避免结果异常。

            【讨论】:

            猜你喜欢
            • 2015-11-11
            • 1970-01-01
            • 2014-11-19
            • 2021-09-05
            • 1970-01-01
            • 2016-01-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多