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

EF Core 7新增对象ID临时值问题:如何自动生成数据库ID?

解决EF Core 7中手动设置负值ID导致的IDENTITY插入错误

问题原因

EF6与EF Core在处理显式设置标识列值的逻辑存在差异:

  • EF6中,当实体标记为Added状态时,即使手动设置了标识列(如Id=-1),只要配置了数据库生成标识值,EF会自动忽略手动值,由数据库生成新ID并同步回实体。
  • EF Core默认会尊重手动设置的标识列值,尝试将其插入数据库,而SQL Server的IDENTITY列默认不允许显式插入值,因此触发报错。

解决方案

通过配置让EF Core在实体新增时忽略手动设置的标识列值,完全沿用数据库生成的ID。

1. 单个实体配置

修改AtCalcConfig类,对Id属性添加SetBeforeSaveBehavior配置:

namespace EFCorePlayground.Config
{
    public class AtCalcConfig : IEntityTypeConfiguration<AtCalc>
    {
        public void Configure(EntityTypeBuilder<AtCalc> builder)
        {
            builder.ToTable("AtCalc");

            // 配置Id为数据库生成,并忽略新增前的手动设置值
            builder.Property(e => e.Id)
                .ValueGeneratedOnAdd()
                .UseIdentityColumn() // 明确指定SQL Server IDENTITY列(可选,但更清晰)
                .Metadata.SetBeforeSaveBehavior(PropertySaveBehavior.Ignore);
                
            builder.HasKey(e => e.Id);
            builder.OwnsOne(e => e.Details);
        }
    }
}

2. 子对象(Owned实体)配置

如果Details子对象也存在相同的负值ID问题,需在OwnsOne配置中同步设置:

builder.OwnsOne(e => e.Details, detailBuilder =>
{
    // 假设Details有Id属性,配置逻辑与主实体一致
    detailBuilder.Property(d => d.Id)
        .ValueGeneratedOnAdd()
        .UseIdentityColumn()
        .Metadata.SetBeforeSaveBehavior(PropertySaveBehavior.Ignore);
        
    // 其他Details属性配置...
});

3. 全局批量配置

如果项目中有多个实体/子对象需要相同配置,可在DbContext的OnModelCreating中统一设置,避免重复代码:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    // 遍历所有实体类型,配置标识列忽略手动值
    foreach (var entityType in modelBuilder.Model.GetEntityTypes())
    {
        var idProperty = entityType.FindProperty("Id");
        if (idProperty != null && idProperty.ValueGenerated == ValueGenerated.OnAdd)
        {
            idProperty.SetBeforeSaveBehavior(PropertySaveBehavior.Ignore);
        }

        // 遍历所有Owned子实体,同步配置
        foreach (var ownedType in entityType.GetOwnedTypes())
        {
            var ownedIdProperty = ownedType.FindProperty("Id");
            if (ownedIdProperty != null && ownedIdProperty.ValueGenerated == ValueGenerated.OnAdd)
            {
                ownedIdProperty.SetBeforeSaveBehavior(PropertySaveBehavior.Ignore);
            }
        }
    }

    // 应用其他实体配置
    modelBuilder.ApplyConfiguration(new AtCalcConfig());
}

效果验证

配置完成后,执行原新增代码:

var m = new AtCalc { Id = -1, Name = "bob" };
context.Add(m);
context.SaveChanges();

EF Core会自动忽略手动设置的Id=-1,由SQL Server生成新的IDENTITY值,并将生成的ID同步回实体对象,同时更新所有本地引用,与EF6的行为一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 07:35:34