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

Entity Framework为何在首个元素后将枚举字段设为Null?

EF Core 更新实体时仅首个项状态字段生效,后续项状态为Null的问题

执行Handler前:
执行Handler前

执行Handler后:
执行Handler后显示Null状态

我在使用Entity Framework时遇到以下问题:调用Exported()方法更新CaapListItem实体时,仅第一个项的Status字段成功更新,后续项该字段被插入为Null,但其他字段更新正常。

调试发现每个caaplistitem都被分配了正确的Status,但Entity Framework执行SaveChanges()时该字段被清除,SQL Profiler显示两个元素的Status被设为Null。请问是否存在枚举类与EF兼容的已知Bug?

CaapListItem类

public class CaapListItem : Entity, IAggregateRoot, IDeletable
{
    public Guid Guid { get; protected set; }
    public int AgreementId { get; private set; }
    public int UserId { get; private set; }
    public CaapStatus? Status { get; private set; }
    public DateTime DateAddedToReadyForExport { get; private set; }
    public DateTime? DateExported { get; private set; }
    public DateTime? DateImported { get; private set; }
    public string? ExportFilePath { get; private set; }
    public string? ImportFilename { get; private set; }

    private bool _delete;
    public bool Delete => _delete;

    public CaapListItem(int agreementId, int userId)
    {
        Guid = Guid.NewGuid();
        AgreementId = agreementId;
        UserId = userId;
    }

    private CaapListItem() { }

    public void ReadyForExport()
    {
        this.Status = CaapStatus.ReadyForExport;
        DateAddedToReadyForExport = DateTime.Now;
    }

    /// <summary>
    /// 将项标记为已导出
    /// </summary>
    public void Exported(string exportFilePath)
    {
        this.Status = CaapStatus.Exported;
        this.DateExported = DateTime.Now;
        this.ExportFilePath = exportFilePath;
        this.AddDomainEvent(new CaapListItemExportedDomainEvent(AgreementId));
    }
}

CaapStatus枚举类

public class CaapStatus : Enumeration
{
    public static readonly CaapStatus ReadyForExport = new(1, nameof(ReadyForExport));
    public static readonly CaapStatus Exported = new(2, nameof(Exported));
    public static readonly CaapStatus Imported = new(3, nameof(Imported));

    private CaapStatus()
    {
    }

    private CaapStatus(int id, string name)
        : base(id, name)
    {
    }
}

调用Export并保存的Handler代码

public async Task<AggregateRootGuid> Handle(CaapExportCommand request,
    CancellationToken cancellationToken)
{
    var agreements = await _context.Agreements.Include(a => a.Terminals)
        .Where(t => request.AgreementIds.Contains(t.Guid)).ToArrayAsync()
        ?? throw new NullReferenceException($"未找到ID为{request.AgreementIds}的协议,请确认协议存在。");

    var calledOffAgreements = Array.ConvertAll(agreements, item => (CalledOffAgreement)item);
    // 导出到CSV
    var caapResults = _caapExportService.GetCaapFieldsForExport(calledOffAgreements);
    var exportFilePath = _caapExportService.ExportToCsv(caapResults);

    foreach (var agreement in calledOffAgreements)
    {
        var caapListItem = await _context.CaapList
       .FirstOrDefaultAsync(t => t.AgreementId! == agreement.Id) ??
            throw new NullReferenceException($"未找到ID为{agreement.Id}的Caap列表项,请确认协议存在且在导出列表中。");

        caapListItem.Exported(exportFilePath);
    }

    await _context.SaveChangesAsync(cancellationToken);

    return new AggregateRootGuid(request.AgreementIds[0]);
}

EF类型配置

internal class EFCaapListItemConfig : IEntityTypeConfiguration<CaapListItem>
{
    public void Configure(EntityTypeBuilder<CaapListItem> builder)
    {
        builder.ToTable("CaapList");
        builder.OwnsOne(a => a.Status, status =>
        {
            status.Property(p => p.Id).HasColumnName("CaapStatusId");
            status.Ignore(p => p.Name);
        });
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 13:05:25