【问题标题】:How to tell Entity Framework that my ID column is auto-incremented (AspNet Core 2.0 + PostgreSQL)?如何告诉 Entity Framework 我的 ID 列是自动递增的(AspNet Core 2.0 + PostgreSQL)?
【发布时间】:2018-10-16 13:59:16
【问题描述】:

代码很简单。 Tag.cs实体:

public partial class Tag
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
}

HomeController.cs类:

public async Task<IActionResult> Index()
{
   tagRepository.Insert(new Tag 
               { 
                   Name = "name", 
                   Description = "description" 
               });
   await UnitOfWork.SaveChangesAsync();  // calls dbContext.SaveChangesAsync()

   return View();
}

TagRepository.cs类:

    // Context it's a usual DBContext injected via Repository's constructor
    public virtual void Insert(TEntity item)
                => Context.Entry(item).State = EntityState.Added;

Tag 表是通过运行创建的:

CREATE TABLE Tag (
    ID SERIAL PRIMARY KEY,
    Name text NOT NULL,
    Description text NULL
);

运行我的应用程序时出现错误:

fail: Microsoft.EntityFrameworkCore.Database.Command[20102]
      Failed executing DbCommand (28ms) [Parameters=[@p0='?', @p1='?', @p2='?'], CommandType='Text', CommandTimeout='30']
      INSERT INTO "tag" ("id", "description", "name")
      VALUES (@p0, @p1, @p2);
Npgsql.PostgresException (0x80004005): 23505: duplicate key value violates unique constraint "tag_pkey"
   at Npgsql.NpgsqlConnector.<DoReadMessage>d__157.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
   at Npgsql.NpgsqlConnector.<ReadMessage>d__156.MoveNext()

如您所见,Entity Framework 尝试将 id=0 值发送到 DB,但我的 DB 中已经有一条带有 id=0 的记录,这就是它抛出 duplicate key 错误的原因。

到目前为止我没有找到任何答案,我的问题是:我怎样才能摆脱这个错误并告诉 Entity Framework 我的id 列是自动递增的,不需要更新它?

【问题讨论】:

    标签: asp.net-core entity-framework-core auto-increment npgsql


    【解决方案1】:

    在浪费了大量时间研究之后,我完全出乎意料地解决了这个问题。实际上,我的问题的解决方案就在表面上,因为问题不在 EF 中,也不在它的东西上。就我而言,它是SEQUENCE。我的意思是,涉及的表有序列列,相关的序列只是被一些副作用改变了。换句话说 - 序列从 1 重新启动,同时表已经具有 1、2、3 等值。这就是 postgres 抛出 'duplicate key' 错误的原因。所以,解决办法是:

    ALTER SEQUENCE "your_table_seq" RESTART WITH your_value;
    

    【讨论】:

      【解决方案2】:

      根据the Postgre SQL docs,这里有一个例子,它展示了如何达到预期的结果:

      protected override void OnModelCreating(ModelBuilder modelBuilder)
         => modelBuilder.Entity<Blog>().Property(b => b.Id).UseIdentityAlwaysColumn();
      

      【讨论】:

      • .UseIdentityAlwaysColumn() 无法解析。您使用的是什么 EF Core 版本?
      • 顺便说一句,我试过 UseNpgsqlIdentityAlwaysColumn()UseNpgsqlSerialColumn() - 这些都不起作用
      • @anatol,嗨。 Microsoft.EntityFrameworkCore.Design - 3.1.3; Microsoft.EntityFrameworkCore.Tools - 3.1.3; Npgsql.EntityFrameworkCore.PostgreSQL - 3.1.3.
      【解决方案3】:

      你必须在这里使用“ValueGenerationOnAdd()”。由于您遇到的问题已在 GitHub 上报告。请找到以下链接。

      https://github.com/npgsql/Npgsql.EntityFrameworkCore.PostgreSQL/issues/73

      您可以从以下链接中找到有关生成值模式的更多信息。

      Value generated on add

      public classs SampleContext:DBContext{
      public DbSet<Tag> Tag { get; set; }
      
      protected override void OnModelCreating(ModelBuilder modelBuilder){
          modelBuilder.Entity<Tag>()
              .Property(p => p.ID)
              .ValueGeneratedOnAdd();
       }
      public class Tag{
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description{get;set;}
        }
      }
      

      来源:-https://www.learnentityframeworkcore.com/configuration/fluent-api/valuegeneratedonadd-method

      希望这会有所帮助

      【讨论】:

      • 我已经从现有数据库生成了上下文(使用命令Scaffold-DbContext),有趣的是我在所有实体中的所有id 属性都是用.Property(p =&gt; p.Id).ValueGeneratedNever() 生成的。我猜这可能是一个错误。无论如何,我已经用.ValueGeneratedOnAdd() 替换了它并且它可以工作。感谢您的链接和解释。
      • 我使用ValueGeneratedOnAdd() 自动创建id,但是不起作用。感谢您或@AndreyKotov 可以看看。见stackoverflow.com/questions/59673778/…
      • 仅供参考,如果您的属性被称为 Id 或 TagId,您不需要手动设置 ValueGeneratedOnAdd - 按照惯例,这是为您完成的(参见 docs.microsoft.com/en-us/ef/core/modeling/…docs.microsoft.com/en-us/ef/core/modeling/…)。
      • 答案中提到的来源与问题无关。问题是关于 Postgre SQL,而不是关于 SQL Server。所以,答案对我不起作用。
      猜你喜欢
      • 2018-06-19
      • 2018-11-05
      • 2013-04-11
      • 2020-07-28
      • 1970-01-01
      • 2017-05-11
      • 1970-01-01
      • 2018-02-23
      • 2017-03-13
      相关资源
      最近更新 更多