C# 在EF和自动递增字段中插入PK CONTAINT

C# 在EF和自动递增字段中插入PK CONTAINT,c#,sql-server,entity-framework,auto-increment,C#,Sql Server,Entity Framework,Auto Increment,我已经让代码运行了大约一周了,突然它在db.saveContext()上给了我一个错误。它插入到一个表中,PK是一个启用自动递增的标识字段 现在,我在代码中输入了一个异常,表示: {“违反主键约束'PK_Acks'。无法在对象'dbo.Acks'中插入重复的键。重复的键值为(12685028)。\r\n语句已终止。} 这对我来说真的很奇怪,因为它会突然成为一个问题 这是我的密码: if (logBufferCounter++ > 1000) {

我已经让代码运行了大约一周了,突然它在
db.saveContext()
上给了我一个错误。它插入到一个表中,PK是一个启用自动递增的标识字段

现在,我在代码中输入了一个异常,表示:
{“违反主键约束'PK_Acks'。无法在对象'dbo.Acks'中插入重复的键。重复的键值为(12685028)。\r\n语句已终止。}

这对我来说真的很奇怪,因为它会突然成为一个问题

这是我的密码:

  if (logBufferCounter++ > 1000)
            {
                logBufferCounter = 0;
                db.SaveChanges();
                recreateContext();
            }
我还尝试删除1000批更新以进行调试。还是同样的错误。我还删除了
recreateContext()
,仍然存在相同的错误

此代码只有一个实例正在运行

可能是什么问题?似乎我遇到了一些低级错误

以下是我创建对象的方式:

  Ack tableItem = new Ack();
        try
        {
            tableItem.messageId = logUtil.getMessageId(tmpPacket);
            tableItem.serverId = logItem.serverId;
            tableItem.time = logUtil.getTime(tmpPacket.getValueOfTag(tcp_packet.pck_tag_types.TM));
            int mr = Convert.ToInt32(tmpPacket.getValueOfTag(tcp_packet.pck_tag_types.MR));
            tableItem.direction = logUtil.getDirection(mr);
            tableItem.isNack = !tmpPacket.is_ack();
            tableItem.unitId = logUtil.getAckUnitId(tmpPacket);

            // Calculate The Client Id
            tcp_packet.pck_item cl;
            if (tmpPacket.find(tcp_packet.pck_tag_types.CL, out cl))
            {
                tableItem.clientId = cl.value;
            }
            else
            {
                tableItem.clientId = null;
            }             

            tableItem.data = tableItem.data.Substring(0, 50);


            // Save to db
            db.Acks.Add(tableItem);
        }
        catch (Exception e)
        {
            log.Error("Could not build tmpItem for an ack packet: " + logItem.payload, e);
        }
我首先在sql server 2012中使用EF 6.1数据库

您应该将自动递增键/值初始化为什么值

[编辑] Ack模型类:

public partial class Ack
{
    public long ackId { get; set; }
    public long messageId { get; set; }
    public byte serverId { get; set; }
    public System.DateTime time { get; set; }
    public bool direction { get; set; }
    public bool isNack { get; set; }
    public string unitId { get; set; }
    public string clientId { get; set; }
    public string data { get; set; }

    public virtual Server Server { get; set; }
}
|下面是sql manager中的表

有时,由于某些意外原因,标识列的种子可能会损坏。正如你所说的,它一直在工作,而且最近出现了错误,我想这就是已经发生的事情(除非你改变了其他任何事情!)

如果是这样,您应该尝试在数据库中运行以下命令:

DBCC CHECKIDENT('SchemaName.TableName', NORESEED)
这将生成当前种子(下一个生成的值是seed+1)

如果数据库中存在下一个值,则必须使用此命令更改种子

DBCC CHECKIDENT('SchemaName.TableName', RESEED)

有关更多信息,请参见:。

您不应该将PK初始化为任何内容。如果您使用的是Code First fluent配置,并且您的主键属性名为Id或AckId,那么EF将假定该属性是您的PK,并且是一个自动递增的标识字段。Ack对象上的什么属性是PK?Acks PrimaryKey的映射是什么?这个映射的sql定义是什么?您不是在尝试插入另一个链接到Ack对象的对象吗?我首先使用的是数据库。我已经签入了我的edmx,并且该字段确实具有
storeGeneratedPattern=idenity
@tschmit007我只是插入那个ack对象,没有链接到它。但是,它确实链接到其他表。
从ACK中选择当前标识('Acks')、max(ackId)返回值(在SSMS中)?感谢您的回复,我不确定,但这两个命令是相同的吗?哎呀,这是一个输入错误。第二个实例应该重新设置种子,而不是取消种子。编辑!如果种子的值为12685029,则下一个插入值将为12685030(前提是它的默认增量为1)。碰撞将发生在这个数字。如果表的值为12685095,则显然存在插入的值的PK大于标识种子。因此,您需要运行RESEED命令。运行时,种子将变为12685095(前提是这是最大现有id),因此下一个插入值为12685096。我建议运行NORESEED来检查是否存在问题,然后重新设置种子以解决问题,以防出现问题。这真的非常奇怪。我从来没有发现过这个问题,也没有听说有人发现了这个问题,除了你;)希望你再也不会犯那样的错误了。第三种CHECKIDENT语法允许手动指定新的种子值(参见文档),因此不必截断表。您应该运行DBCC CHECKDB来检查您的数据库完整性:这看起来一点也不好。不,这与您的问题无关。事实上,它确认了标识不会导致问题:“这不会导致争用条件,因为当插入发生时,标识列总是递增的(它从不回滚),并且scope_identity()总是返回在insert语句范围内生成的标识值”,这是100%正确的。除非运行SET identity\u insert ON,否则无法手动在标识列中插入值:算了吧,我打赌不会再发生这种情况,说真的。