【问题标题】:It is normal an Identity field increment your value even when a operation fail?即使操作失败,身份字段也会增加您的值是正常的吗?
【发布时间】:2014-01-07 13:31:33
【问题描述】:

我正在使用 Migration 通过Update-Database 命令在 SQL Server 数据库中播种我的表。但是当这个过程由于某种原因(例如 FK 问题)失败时,我的具有自动增量 ID 的模型的种子将会增加。

让我们看一个例子......

具有自动增量 ID 的示例模型:

public class Person
{
    public int Id { get; set; }

    public string Name { get; set; }
}

我们可以在Configuration.cs 中播种这个模型:

context.Persons.AddOrUpdate(t => t.Name,
    new Person { Name = "Alex" },
    new Person { Name = "Louis" },
    new Person { Name = "Willian" }
);

假设我的数据库是空的,当我运行 Update-Database 时,我将在 Person 表(Alex、Louis、Willian)中有 3 行 ID 为 1、2 和 3。但如果在此过程中出现问题并且我再次运行Update-Database,但现在成功了,ID 将为 4、5 和 6。

要纠正这个问题,我需要通过 SQL 重新设置身份字段。

这是正常行为吗? 我可以做些什么来保证从 1 开始的顺序 ID,而无需删除 Identity 属性并修复 ID 值? 有更好的方法来填充我的表格吗?

【问题讨论】:

  • 是的,这是正常行为。如果例如一个INSERT 被回滚,发出的身份值是“丢失”。如果你删除了一些行,这并不意味着标识值会减少。身份值 - 一旦发送 - 就从不“回收”
  • “我可以做一些事情来保证顺序 ID” - 实现这一点非常“昂贵”,因为它是可伸缩性的一个相当大的限制因素。请确定,真的确定您确实需要您的IDs 在沿着这条路线走之前拥有这个属性。标识列不应该显示给您的用户,因此它们的实际数值不应该真正重要。
  • @Damien_The_Unbeliever 遗憾的是,我不是数据库专家。我在与其他表的关系中使用这些 ID。典型的例子,我播种了两个名为 Parent 和 Child 的表。我希望两者都有顺序 ID。然后我可以使用该 ID 在父母和孩子之间建立关系。我知道,正确的方法是通过另一个键(例如名称)查找行,然后检索正确的 ID。但是,当我为 10 个或更多具有大量行的表播种并建立关系时,有一种简单的方法可以做到这一点吗?
  • 如果您假设所有表的 ID 都是前面的,那么您可能会发现,是的,父表中添加了 10 行,但是例如您假设将收到 ID 1 的行实际上收到了 ID 6。如果您觉得这没问题,那么我认为这只是测试数据 - 我不会将数据库设计约束建立在仅用于测试目的的东西上。跨度>

标签: c# sql-server entity-framework entity-framework-migrations


【解决方案1】:

是的,这就是身份列的工作方式。标识列不保证单调递增的数字。它只是根据需要按顺序分配数字,因此您不必这样做。

身份的分配可以在交易失败之前发生。即使不使用这些值,标识仍会递增。如果您尝试通过重置来更正该值,则会导致冲突。

例如,第 1、2 和 3 行以标识 1、2 和 3 插入。然后发生 ROLLBACK,因此从表中删除行。同时,插入4、5和6。您看到 1、2 和 3 丢失了,因此您将身份设置回原处。当插入 1、2、3 时,标识现在是 4,所以下一次插入会有重复的主键。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-21
    • 2018-11-18
    • 2017-12-06
    • 1970-01-01
    • 1970-01-01
    • 2017-07-15
    • 2012-04-23
    • 2014-11-17
    相关资源
    最近更新 更多