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

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似乎正在获取一

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

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

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
    将临时密钥的所有实例替换为新的永久密钥

您也可以发布“myObject”类代码吗?至少主键字段的声明是先创建代码的模型?先创建数据库的模型。我说带他出去,踢他一脚,然后踢他:这是有趣的信息。。。然而,这并不能解释为什么EF试图为一个对象分配一个已经存在的id。@Nick我想知道当您尝试该操作时,您的上下文是最新的,并且上下文是共享的吗?@Nick Ah刚刚阅读了您的更新,您的上下文确实过时了。是的,表的种子值是100,然而,在此之前有数百个记录值。这尤其令人沮丧,因为它是几个月前出现的,我认为我已经压扁了它,只是在运行脚本后它露出了丑陋的脑袋——直到现在我才将这两个事件联系在一起>。