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,否则无法手动在标识列中插入值:算了吧,我打赌不会再发生这种情况,说真的。