npgsql - Npgsql - 使用“始终作为身份生成”
问题描述
我目前正在尝试使用 Npgsql(版本 3.1.3)使用官方文档(Npgsql.org)将记录插入到具有生成标识的表中。但我总是得到错误:
Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details.
---> Npgsql.PostgresException (0x80004005): 428C9: cannot insert into column "mitteilung_id"
我已经发现了几个关于这个主题的问题,但它们要么已经过时(版本 2 或更低),要么不起作用。
我的项目结构如下。表定义如下所示:
CREATE TABLE mitteilung
(
mitteilung_id INTEGER GENERATED ALWAYS AS IDENTITY
CONSTRAINT mitteilung_pk
PRIMARY KEY,
betreff TEXT
CONSTRAINT mitteilung_nn_betreff
CHECK (betreff IS NOT NULL)
CONSTRAINT mitteilung_ck_length_betreff
CHECK (length(betreff) <= 100),
nachricht TEXT
CONSTRAINT mitteilung_ck_length_nachricht
CHECK (length(nachricht) <= 500)
CONSTRAINT mitteilung_nn_nachricht
CHECK (nachricht IS NOT NULL),
erfasst_am TIMESTAMP WITH TIME ZONE
CONSTRAINT mitteilung_nn_erfasst_am
CHECK (erfasst_am IS NOT NULL)
);
我已将实体定义如下:
public class Mitteilung : ISlongooEntity
{
public int MitteilungId { get; set; }
...
我还尝试将以下属性添加到 ID 属性:
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
在数据库上下文中,我测试了以下设置来解决问题。
modelBuilder.Entity<Mitteilung>()
.Property(b => b.MitteilungId)
.UseIdentityAlwaysColumn();
modelBuilder.Entity<Mitteilung>()
.Property(b => b.MitteilungId)
.Metadata.SetValueGenerationStrategy(NpgsqlValueGenerationStrategy.IdentityAlwaysColumn);
modelBuilder.Entity<Mitteilung>()
.Property(b => b.MitteilungId)
.Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Ignore);
但无论我使用哪种组合设置,在尝试保存实体时都会收到上述错误消息。我也不太明白为什么在进行更新时会尝试更新 ID。我究竟做错了什么?
public Mitteilung Save(Mitteilung obj)
{
var addedObj = Context.Mitteilungen.Add(obj);
// Context.Entry(obj).Property(x => x.MitteilungId).IsModified = false;
Context.SaveChanges();
return addedObj.Entity;
}
解决方案
下面的代码确实可以正常工作。
请注意,EF Core 将自动检测这MitteilungId
是 的主键Mitteilung
,并且由于它是一个 int,因此会将其设置为GENERATED BY DEFAULT AS IDENTITY
. 换句话说,您不需要任何流畅的 API 调用 - 或[Key]
or[DatabaseGenerated]
注释 - EF Core 将按照约定正确设置。
如果由于某种原因,您需要GENERATED ALWAYS AS IDENTITY
(而不是BY DEFAULT
),则可以使用下面的 fluent API 调用。
如果您仍然遇到问题,您能否更改下面的代码示例以产生错误?
class Program
{
static async Task Main(string[] args)
{
await using var ctx = new BlogContext();
await ctx.Database.EnsureDeletedAsync();
await ctx.Database.EnsureCreatedAsync();
ctx.Blogs.Add(new Mitteilung { Name = "foo" });
await ctx.SaveChangesAsync();
}
}
public class BlogContext : DbContext
{
public DbSet<Mitteilung> Blogs { get; set; }
static ILoggerFactory ContextLoggerFactory
=> LoggerFactory.Create(b => b.AddConsole().AddFilter("", LogLevel.Information));
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseNpgsql("...")
.EnableSensitiveDataLogging()
.UseLoggerFactory(ContextLoggerFactory);
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Mitteilung>()
.Property(b => b.MitteilungId)
.UseIdentityAlwaysColumn();
}
}
public class Mitteilung
{
public int MitteilungId { get; set; }
public string Name { get; set; }
}
推荐阅读
- php - 使用 jquery 和 php 动态重命名侧边栏菜单
- iis - 部署多个生产环境
- jquery - 调整大小时的动态值
- javascript - if 块中具有不同数值的这个数字函数的含义
- tabs - 从 TabView Flutter 打开屏幕而不是全屏
- ubuntu - Windows 的 linux 子系统在哪里寻找 SSH 密钥?
- git - Azure devops - 服务器端 git 挂钩
- java - 在 GCP 上运行 spring boot 应用程序:nginx 反向代理:加载资源失败:服务器响应状态为 502 (Bad Gateway)
- android - Android EditText MultiLine 可绘制重力
- knockout.js - 如何使用带有 KnockoutJS 的 JQuery DataTables 添加事件点击