【问题标题】:Ef core code first Error : Key ("Id")=(33) already existsEf core code first Error : Key ("Id")=(33) already exists
【发布时间】:2022-01-05 14:42:30
【问题描述】:

我在一个 asp.net 核心项目中为 Destinations 表做一个粗略的处理。 (使用ef核心代码第一法)

当创建一个新的目的地时,我在调试控制台中遇到了这样的错误。

Exception data:
    MessageText: duplicate key value violates unique constraint "PK_Destinations"
    Detail: Key ("Id")=(33) already exists.
    SchemaName: public
    TableName: Destinations
    ConstraintName: PK_Destinations

由于某些原因,我们已经创建了一个 Destinations 表并手动添加了数据。现在为那张桌子做点菜。我想这就是为什么会出现这个错误 Key ("Id")=(33) already exists.

DbContext.cs

public DbSet<Destination> Destinations { get; set; }

service.cs

  public async Task<Destination> Create(Destination destination)
        {
            await _catalogDbContext.Destinations.AddAsync(destination);
            await _catalogDbContext.SaveChangesAsync();
            return destination;
        }

我的问题是

  • 我的表中有 100 行。我们不能删除它们。 因此,添加新目的地时,目的地 id 应从 301 开始。

  • 我们的开发数据库在我们的表中有 200 行。我们不能删除它们。 因此,添加新目的地时,目的地 id 应从 201 开始。

  • 我们的生产数据库在我们的表中有 240 行。我们不能删除它们。 因此,添加新目的地时,目的地 id 应从 241 开始。

我怎么办,当创建一个目标ID应该从101、201或241开始。并且在添加一个新的ID后应该自动增加。?

编辑: 目的地.cs

public class Destination
    {
        [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; private set; }

        [Required]
        public string Continent { get; set; }

        [Required]
        public string Country { get; set; }

        [Required]
        public string Iso { get; set; }

        [Required]
        public string Name { get; set; }
}

【问题讨论】:

  • 请向我们展示Destination 类的外观,以及您传递给Create() 方法的destination 对象。 :)
  • 让数据库生成ID怎么样。将列设置为标识,告诉 EF ID 是数据花瓶生成的,当您将实体添加到上下文时不要提供 ID 值,当您保存它们时,EF 将检索 Id 并使用它更新实体,以便您可以使用它,如果您关心
  • @thesystem @Caius 请检查问题。我已经用Destination.cs 进行了编辑。 ID 是[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; private set; }
  • 你知道 33 是​​从哪里来的吗?为什么它尝试创建所有值的 ID 为 33 的行?我们可以先看看您是如何通过代码创建表格的吗?可能在 DbContext 中使用 modelbuilder 完成
  • 另外,您可以将 Id 更改为 GUID,这样您每次都可以确保唯一的值。

标签: c# postgresql entity-framework-core ef-code-first asp.net-core-webapi


【解决方案1】:

当你添加一个新实体时,最好让Id值作为默认值,不要尝试分配它。 (例如,Id 是int 所以让值 = 0)

public async Task<Destination> Create()
{
     var destination = new Destination
     {
        Continent = "What ever",
        Country = "...."
        // Init all required properties BUT Id
     };

     // At this line, destination.Id == 0 because you didn't assign a value
     await _catalogDbContext.Destinations.AddAsync(destination);
     await _catalogDbContext.SaveChangesAsync();

     // At this line, you should see destination.Id > 0, the value is assigned by EntityFramework
     return destination;
}

【讨论】:

  • 嗨,你检查我的问题了吗?我也这样做过。问题是我已经手动创建了目标表。现在我为目的地做粗加工。现在假设我要创建第一个新目的地 然后,d​​estination.Id = 1。好吗?错误是Key ("Id")=(1) already exists.
  • 我们有两种添加数据的模式。 1个手动设置id,2个自动id,你必须选择1或2。在你的情况下。两者都需要,不推荐。您必须编写自定义逻辑,以便如果 id 已经存在,则执行一些操作。我认为这很容易。请注意,如果您有 id 1、2、3、4。那么您删除 3,所以我们有剩余的 1、2、4 ==> 下一个自动 id 是 5,而不是 3。
  • 好的,谢谢。我会这样检查
【解决方案2】:

您在此处提到的代码 sn-p 没有问题。需要在数据库方面工作。

我的理解是,您的表具有 pk 列 ID,即身份,即自动增量。在这种情况下,您需要重新播种。例如。如果您的表有现有记录,那么您需要获取 id 列的最大值;假设 id 列最大值为 200。现在您必须告诉数据库将标识设置为 200。下一次,当插入新记录时,它将以 id=201 存储,依此类推。

重新设置表标识值的步骤如下

DBCC CHECKIDENT ('yourtablename', RESEED, 200)

https://docs.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-checkident-transact-sql?view=sql-server-ver15

【讨论】:

    猜你喜欢
    • 2012-03-24
    • 2018-01-15
    • 2020-04-29
    • 1970-01-01
    • 1970-01-01
    • 2013-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多