You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解决EF Core向带计算主键的SQL Server表插入数据失败问题

解决EF Core插入时尝试写入计算列D_ID的问题

问题根源

你的D_ID是SQL Server的持久化计算列,同时作为主键,但EF Core默认会认为主键需要由应用提供值,即使添加了[DatabaseGenerated]特性,也可能因为主键的特殊处理导致配置未生效,最终生成的Insert语句包含D_ID字段,导致插入失败。

解决方案:使用Fluent API明确配置(推荐)

Fluent API在处理主键+计算列的场景下比数据注解更可靠,以下是具体配置步骤:

1. 实体类定义

确保实体类中不对D_ID进行手动赋值,保持属性定义简洁:

public class TblName
{
    public int ID { get; set; }
    public string D_ID { get; set; }
    public string NAME { get; set; }
    public bool? IS_ENABLED { get; set; }
    public string ADDRESS { get; set; }
}

2. 在DbContext中配置实体

重写OnModelCreating方法,明确告诉EF Core各列的生成规则:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<TblName>(entity =>
    {
        // 配置ID为自增标识列
        entity.Property(e => e.ID)
            .ValueGeneratedOnAdd()
            .UseIdentityColumn();

        // 配置D_ID为数据库计算列,指定计算逻辑并标记为持久化
        entity.Property(e => e.D_ID)
            .HasComputedColumnSql("('DID' + RIGHT('000000' + CONVERT([varchar](6), [ID]), 6))", persisted: true)
            .ValueGeneratedOnAddOrUpdate(); // 插入/更新时均由数据库生成

        // 设置D_ID为主键
        entity.HasKey(e => e.D_ID);

        // 配置NAME字段的唯一约束
        entity.HasIndex(e => e.NAME).IsUnique();

        // 配置IS_ENABLED的默认值(与数据库默认值保持一致)
        entity.Property(e => e.IS_ENABLED)
            .HasDefaultValue(true);
    });
}

3. 插入新记录的正确方式

插入时不要给D_ID和ID赋值,由数据库自动生成:

var newItem = new TblName
{
    NAME = "示例名称",
    ADDRESS = "示例地址"
    // IS_ENABLED可省略,数据库会使用默认值1
};

await _context.TblNames.AddAsync(newItem);
await _context.SaveChangesAsync();

数据注解的替代方案(可选)

如果你更倾向于使用数据注解,确保实体类配置正确,且DbContext中没有覆盖相关配置:

public class TblName
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public string D_ID { get; set; }

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ID { get; set; }

    [Required]
    [MaxLength(50)]
    public string NAME { get; set; }

    [DefaultValue(true)]
    public bool? IS_ENABLED { get; set; }

    [MaxLength(2000)]
    public string ADDRESS { get; set; }
}

注意:这种方式在部分EF Core版本中可能因为主键的特殊逻辑导致配置不生效,因此优先推荐Fluent API方案。

额外注意事项

  • 如果之前已经生成过迁移文件,需要重新生成迁移并更新数据库,确保配置生效。
  • 确认数据库中的D_ID列确实是计算列,没有被手动修改为普通列。

内容的提问来源于stack exchange,提问作者amjee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 05:33:32