Entity Framework Core中使用SQL Server序列遇Id非空错误的求助
问题
我正在开发一个.NET Core应用,构建API的POST端点时遇到问题。我想用数据库中已有的HIBERNATE_SEQUENCE序列对象来保证各表Id的一致性。我尝试了一个方案,在DbContext中添加了以下代码:
public DbSet<Developer> Developer { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Transaction>().ToTable("RtpTransaction"); modelBuilder.HasSequence("HIBERNATE_SEQUENCE"); modelBuilder.Entity<Developer>() .ToTable("Developer") .Property(x => x.Id) .HasDefaultValueSql("NEXT VALUE FOR HIBERNATE_SEQUENCE"); }
之后在控制器创建Developer实体时没有设置Id,期望序列自动填充下一个值,控制器代码如下:
public ActionResult<DeveloperDto> CreateDeveloper(CreateDeveloperDto dto) { Developer newDeveloper = new() { CreatedDate = DateTime.Now, CreatedBy = "RtpDeveloper", LastUpdatedDate = DateTime.Now, LastUpdatedBy = "RtpDeveloper", DevShort = dto.DevShort, DevMedium = dto.DevMedium, Status = dto.Status, DevClob = dto.DevClob }; _context.Add(newDeveloper); _context.SaveChanges(); return Ok(newDeveloper.AsDto()); }
但执行时报错,提示Id不能为空,我可能误解了相关方案的内容。
解决方法
问题出在EF Core的实体验证机制上:HasDefaultValueSql是数据库层面的默认值配置,但EF Core默认会把Id字段标记为必填项,在执行插入操作前会先验证实体的必填字段是否为空,此时它不知道Id会由数据库生成,所以直接抛出错误。
你需要做以下调整:
配置EF Core识别Id由数据库生成
在实体的Id属性配置中添加ValueGeneratedOnAdd(),明确告诉EF Core这个字段的值会在插入时由数据库生成,跳过客户端的非空验证:modelBuilder.Entity<Developer>() .ToTable("Developer") .Property(x => x.Id) .HasDefaultValueSql("NEXT VALUE FOR HIBERNATE_SEQUENCE") .ValueGeneratedOnAdd(); // 添加该行确认数据库序列存在且可访问
确保数据库中已经存在HIBERNATE_SEQUENCE序列,且当前数据库用户拥有访问该序列的权限。如果序列还未创建,可以通过SQL语句手动创建,或者通过EF Core迁移生成。
如果使用的是EF Core 3.0及以上版本,也可以用更简洁的UseHiLo模式绑定已有序列,这种方式更贴合EF Core的设计:
modelBuilder.Entity<Developer>() .ToTable("Developer") .Property(x => x.Id) .UseHiLo("HIBERNATE_SEQUENCE");
调整完成后,EF Core会跳过Id字段的客户端非空验证,交由数据库通过序列生成值,并且插入后会自动将生成的Id回填到实体对象中。
内容的提问来源于stack exchange,提问作者Kenneth Clarke
相关产品推荐
相关产品推荐

