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

如何在Entity Framework中配置自定义字符串ID生成器

解决方案

首先请先将你需要使用的自定义字符串ID生成器实现引入到项目中,本文示例中我们将该生成器类命名为DefaultIdGenerator,其提供GenerateUniqueId()方法返回唯一字符串ID。

方法1:重写DbContext的SaveChanges方法(推荐,适配性强)

该方法无需修改模型配置,所有包含字符串类型Id属性的实体会自动统一适配规则:

  1. 将ID生成器注册到依赖注入容器
    .NET 5 中在Startup.cs的ConfigureServices方法中添加如下代码:
services.AddSingleton<DefaultIdGenerator>();
  1. 在自定义DbContext中注入生成器,并重写保存方法
public class AppDbContext : DbContext
{
    private readonly DefaultIdGenerator _idGenerator;

    public AppDbContext(DbContextOptions<AppDbContext> options, DefaultIdGenerator idGenerator) : base(options)
    {
        _idGenerator = idGenerator;
    }

    public DbSet<Product> Products { get; set; }

    public override int SaveChanges()
    {
        GenerateIdsForAddedEntities();
        return base.SaveChanges();
    }

    public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
    {
        GenerateIdsForAddedEntities();
        return base.SaveChangesAsync(cancellationToken);
    }

    private void GenerateIdsForAddedEntities()
    {
        // 筛选所有处于新增状态的实体
        var addedEntities = ChangeTracker.Entries()
            .Where(e => e.State == EntityState.Added);

        foreach (var entry in addedEntities)
        {
            // 检查是否存在字符串类型且为空的Id属性
            var idProperty = entry.Property("Id");
            if (idProperty.Metadata.ClrType == typeof(string) && string.IsNullOrWhiteSpace(idProperty.CurrentValue as string))
            {
                idProperty.CurrentValue = _idGenerator.GenerateUniqueId();
            }
        }
    }
}

方法2:使用EF Core原生自定义值生成器

该方法基于EF Core官方的值生成机制实现,规则配置更灵活:

  1. 实现自定义值生成器类
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.ValueGeneration;

public class CustomStringIdGenerator : ValueGenerator<string>
{
    private readonly DefaultIdGenerator _idGenerator;

    public CustomStringIdGenerator(DefaultIdGenerator idGenerator)
    {
        _idGenerator = idGenerator;
    }

    // 标记生成的是永久值,不是EF临时值
    public override bool GeneratesTemporaryValues => false;

    public override string Next(EntityEntry entry)
    {
        return _idGenerator.GenerateUniqueId();
    }
}
  1. 在OnModelCreating方法中配置值生成规则
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    // 单独为Product实体配置
    modelBuilder.Entity<Product>()
        .Property(p => p.Id)
        .HasValueGenerator<CustomStringIdGenerator>();

    // 如需批量为所有带string类型Id的实体配置,可使用如下代码
    /*
    var stringIdEntities = modelBuilder.Model.GetEntityTypes()
        .Where(t => t.FindProperty("Id")?.ClrType == typeof(string));
    foreach (var entityType in stringIdEntities)
    {
        entityType.FindProperty("Id")
            .SetValueGeneratorFactory((_, __) => new CustomStringIdGenerator(new DefaultIdGenerator()));
    }
    */
}

注意:实体的Id属性不要配置为数据库生成(比如不要加[DatabaseGenerated(DatabaseGeneratedOption.Identity)]注解),否则EF会忽略自定义生成的ID值,等待数据库返回ID。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 02:18:03