尝试使用实体框架将记录插入SQL Server时发生违反主键错误

本文关键字:错误 Server SQL 实体 框架 插入 记录 | 更新日期: 2023-09-27 18:29:58

违反PRIMARY KEY约束"PrimaryKeyId"。无法在对象"dbo.Table"中插入重复的键。重复的键值为(xxx)。''''r''n语句已终止。

这已经断断续续地发生了好几个星期了,每次我想我都会把它修好,几天后就会突然出现。我正在使用:

dbContext.Table.Add(myObject);
dbContext.SaveChanges();

这是在using语句中,试图添加当前id为0的对象。PrimaryKeyId是表中的标识,并设置为自动递增1。然而,实体框架似乎正在获取一个随机Id,并试图将其分配给我的对象,然后将所述对象添加到数据库中。

这种情况只发生在这一个表上,而在许多其他表上也使用了相同的过程,没有任何问题。正在执行操作的表的设置与使用此过程的其他表相同,没有错误。关于是什么原因导致了这种情况,有什么想法吗?为了澄清,实体框架似乎试图将一个已经存在的主键分配给一个新对象。

我的特定问题的解决方案:给DBA涂柏油

说明:在运行一个冗长/复杂的导入脚本时,我们的DBA将其设置为将表重新设定为x,该值远低于标识列中的当前值。因此,从技术上讲,过去几周并没有出现任何问题,只是人为失误。这个问题可以/应该/也许应该拖到一个木棚后面,摆脱它的痛苦。顺便说一句,诽谤是他的建议(我不赞成未经同事同意就辱骂他们)。

如果这个问题没有被删除,建议的修复方法是使用检查表上的当前标识值

 select ident_current('tableName') 

并将其与表中的最高值进行比较。特别是如果通过脚本手动导入/修改种子,则可能会手动重置种子。

尝试使用实体框架将记录插入SQL Server时发生违反主键错误

这应该很有帮助(尤其是我加粗的那一段):取自使用实体密钥

实体密钥和添加的对象

创建新实体时,实体框架会定义临时键并将IsTemporary属性设置为true。当您调用SaveChanges方法时,实体框架会分配一个永久键,并将IsTemporary属性设置为false。

如果相应的列值是在数据库中生成的标识,请将存储模型中实体的属性元素的StoreGeneratedPattern属性设置为Identity。当实体数据模型工具从现有数据源生成数据模型时,StoreGeneratedPattern属性将添加到表示数据源中的标识或计算列的每个属性元素(CSDL)元素中。实体框架用数据源在调用SaveChanges后生成的标识值替换临时键中的属性值

以下详细说明了用包含服务器生成值的永久密钥替换临时密钥的内部过程:

  • 将构造实体对象
  • 此时,键属性都具有默认值,要么为null,要么为0
  • 通过调用ObjectContextObjectSet上的AddObject方法,或者通过将对象添加到关系"多"端的对象集合,将新对象添加到ObjectContext
  • 此时,实体框架生成一个临时密钥,用于将对象存储在ObjectStateManager
  • 在ObjectContext上调用SaveChanges
  • INSERT语句由实体框架生成并在数据源上执行
  • 如果INSERT操作成功,则服务器生成的值被写回ObjectStateEntry
  • ObjectStateEntry使用服务器生成的值更新对象
  • 当在ObjectStateEntry上调用AcceptChanges时,通过使用新的服务器生成的值来计算永久EntityKey
  • AcceptChangesSaveChanges执行结束时自动调用,或者在使用AcceptAllChangesAfterSave标志调用SaveChanges方法时自动调用
  • CCD_ 23用新的永久密钥替换临时密钥的所有实例