C# 尝试使用实体框架将记录插入SQL Server时违反主键错误
违反主键约束“PrimaryKeyId”。无法在对象“dbo.Table”中插入重复键。重复的键值为(xxx)。\r\n语句已终止 这已经断断续续地发生了好几个星期了,每次我想我把它修好了,几天后它就会突然出现。我正在使用:C# 尝试使用实体框架将记录插入SQL Server时违反主键错误,c#,.net,entity-framework,C#,.net,Entity Framework,违反主键约束“PrimaryKeyId”。无法在对象“dbo.Table”中插入重复键。重复的键值为(xxx)。\r\n语句已终止 这已经断断续续地发生了好几个星期了,每次我想我把它修好了,几天后它就会突然出现。我正在使用: dbContext.Table.Add(myObject); dbContext.SaveChanges(); 这在using语句中,正在尝试添加当前id为0的对象。PrimaryKeyId是表中的标识,设置为自动递增1。然而,EntityFramework似乎正在获取一
dbContext.Table.Add(myObject);
dbContext.SaveChanges();
这在using语句中,正在尝试添加当前id为0的对象。PrimaryKeyId
是表中的标识,设置为自动递增1。然而,EntityFramework似乎正在获取一个随机Id,并试图将其分配给我的对象,然后将该对象添加到数据库中
这只发生在这一个表上,并且在许多其他表上使用了相同的过程,没有任何问题。对其执行操作的表的设置与使用此过程的其他表相同,没有错误。你知道是什么导致了这一切吗?为了澄清这一点,EntityFramework似乎正在尝试将一个已经存在的主键分配给一个新对象
我的具体问题的解决方案:为DBA添加焦油和羽毛
说明:在运行冗长/复杂的导入脚本时,我们的DBA将其设置为在x处为表重新设定种子,这远远低于标识列中的当前值。所以在过去的几周里,技术上没有问题,这只是人为的错误。这个问题可以/应该/也许应该拖到一个木屋后面,摆脱它的痛苦。顺便说一句,涂黑/羽化是他的建议(我不赞成未经同事同意而虐待他们)
如果未删除此问题,建议的修复方法是使用检查表上的当前标识值
select ident_current('tableName')
并将其与表中的最高值进行比较。特别是如果通过脚本进行手动导入/修改,其中种子可能会被手动重置。这应该会有帮助(特别是我用粗体表示的段落):摘自
实体键和添加的对象
创建新实体时,实体框架将定义临时键并将IsTemporary属性设置为true。调用SaveChanges方法时,实体框架将分配一个永久键,并将IsTemporary属性设置为false
如果对应的列值是在数据库中生成的标识,则将存储模型中实体的属性元素的StoreGeneratedPattern
属性设置为identity
。当实体数据模型工具从现有数据源生成数据模型时,StoreGeneratedPattern
属性将添加到表示数据源中的标识或计算列的每个属性元素(CSDL)元素中。实体框架将临时键中的属性值替换为调用SaveChanges
后由数据源生成的标识值。
以下详细说明了将临时密钥替换为包含服务器生成值的永久密钥的内部过程:
- 构造实体对象
- 此时,键属性都有默认值,要么为null,要么为0
- 通过调用
或ObjectContext
上的ObjectSet
方法,或者通过向关系“多”端的对象集合添加对象,可以将新对象添加到AddObject
ObjectContext
- 此时,实体框架生成一个临时键,用于将对象存储在
中ObjectStateManager
- 在ObjectContext上调用
SaveChanges
- 实体框架生成
语句并在数据源上执行INSERT
- 如果
操作成功,服务器生成的值将写回INSERT
ObjectStateEntry
使用服务器生成的值更新对象ObjectStateEntry
- 在
上调用ObjectStateEntry
时,将使用新的服务器生成的值计算永久AcceptChanges
EntityKey
在执行AcceptChanges
结束时自动调用,或者使用SaveChanges
标志调用AcceptAllChangesAfterSave
方法时自动调用SaveChanges
将临时密钥的所有实例替换为新的永久密钥ObjectStateManager