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

EF Code First模式下如何单次生成符合规则的唯一QuotationNo字段值

更简便的QuotationNo生成方案

针对你目前两次调用SaveChanges生成QuotationNo的场景,有几种更简洁的实现方式:

1. 简化现有代码(无需显式Update)

你的现有代码里,第二次调用SaveChanges前不需要执行_db.Quotations.Update(quot)——因为实体添加并执行SaveChanges后,EF Core仍在跟踪该实体的状态,直接修改属性后调用SaveChanges,EF会自动生成更新语句。简化后的代码如下:

if (ModelState.IsValid)
{
     _db.Quotations.Add(quot);
     _db.SaveChanges(); // 获取自增主键ID
     
     // 直接修改被跟踪的实体属性
     quot.QuotationNo = $"QUOT/{DateTime.Today:MM-yy}/{quot.Id:D5}";
     _db.SaveChanges(); // 自动触发更新,无需显式调用Update
}

2. 数据库计算列(推荐,彻底避免两次SaveChanges)

如果你的数据库支持计算列(如SQL Server、PostgreSQL),可以将QuotationNo设为持久化计算列,由数据库自动生成格式值,业务代码只需一次SaveChanges即可完成操作。

操作步骤:

(1)修改实体类

给QuotationNo添加特性,告知EF该列由数据库维护:

public class Quotation
{
    [Key]
    public int Id { get; set; } // PK
    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public string QuotationNo { get; set; } // 由数据库自动生成格式值
}

(2)配置计算列

  • 若使用SQL Server,直接执行SQL语句修改表:
ALTER TABLE Quotations
ADD QuotationNo AS 'QUOT/' + FORMAT(GETDATE(), 'MM-yy') + '/' + RIGHT('00000' + CAST(Id AS VARCHAR(5)), 5) PERSISTED;
  • 若使用Code First,可在DbContext的OnModelCreating中配置:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Quotation>()
        .Property(q => q.QuotationNo)
        .HasComputedColumnSql("'QUOT/' + FORMAT(GETDATE(), 'MM-yy') + '/' + RIGHT('00000' + CAST(Id AS VARCHAR(5)), 5)", stored: true);
}

配置完成后,添加Quotation实体并调用一次SaveChanges,数据库会自动生成符合格式的QuotationNo,无需额外更新操作。

3. 封装逻辑到DbContext的SaveChanges方法

如果不想修改数据库结构,可以将生成QuotationNo的逻辑封装到DbContext的SaveChanges重写中,让业务代码更简洁:

public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
    // 筛选出所有新增状态的Quotation实体
    var addedQuotations = ChangeTracker.Entries<Quotation>()
        .Where(e => e.State == EntityState.Added)
        .ToList();

    // 先执行基础SaveChanges获取自增ID
    var result = base.SaveChanges(acceptAllChangesOnSuccess);

    // 为新增实体设置QuotationNo并标记为修改状态
    foreach (var entry in addedQuotations)
    {
        var quot = entry.Entity;
        quot.QuotationNo = $"QUOT/{DateTime.Today:MM-yy}/{quot.Id:D5}";
        entry.State = EntityState.Modified;
    }

    // 再次保存更新
    if (addedQuotations.Any())
    {
        result += base.SaveChanges(acceptAllChangesOnSuccess);
    }

    return result;
}

业务代码只需调用一次SaveChanges即可:

if (ModelState.IsValid)
{
     _db.Quotations.Add(quot);
     _db.SaveChanges(); // 内部自动完成两次保存逻辑
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 00:45:29