如何告诉 Entity Framework 我的 ID 列是自动递增的(AspNet Core 2.0 + PostgreSQL)?
Posted
技术标签:
【中文标题】如何告诉 Entity Framework 我的 ID 列是自动递增的(AspNet Core 2.0 + PostgreSQL)?【英文标题】:How to tell Entity Framework that my ID column is auto-incremented (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
列是自动递增的,不需要更新它?
【问题讨论】:
【参考方案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 Descriptionget;set;
来源:-https://www.learnentityframeworkcore.com/configuration/fluent-api/valuegeneratedonadd-method
希望这会有所帮助
【讨论】:
我已经从现有数据库生成了上下文(使用命令Scaffold-DbContext
),有趣的是我在所有实体中的所有id
属性都是用.Property(p => p.Id).ValueGeneratedNever()
生成的。我猜这可能是一个错误。无论如何,我已经用.ValueGeneratedOnAdd()
替换了它并且它可以工作。感谢您的链接和解释。
我使用ValueGeneratedOnAdd() 自动创建id,但是不起作用。感谢您或@AndreyKotov 可以看看。见***.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。所以,答案对我不起作用。以上是关于如何告诉 Entity Framework 我的 ID 列是自动递增的(AspNet Core 2.0 + PostgreSQL)?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Entity Framework Code First 让我的数据库播种?
如何在 Entity Framework 4.4 中实现 DBSet.AddOrUpdate?
如何将 Entity Framework 4.1 与 MVC 3 登录一起使用
如何让 Visual Studio 发布 Web 向导相信我的数据库是 Entity Framework CodeFirst?