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

.NET Core 7中如何通过AutoMapper忽略空值?

如何通过AutoMapper全局忽略未填写的空值字段

我使用.NET Core 7.0和AutoMapper 12,通过Postman向Company表发送如下JSON:

{
  "id": 1002,
  "name": "xcv"
}

但未提交的字段(比如description)会被自动设为null更新到数据库。我希望通过AutoMapper全局配置,忽略CompanyUpdateDto中用户未填写的空值,但现有配置没生效。相关代码如下:

相关代码

Company实体

public class Company
{
    public int Id { get; set; }
    public string? Name { get; set; }
    public string? Description { get; set; }
    public DateTime? CreatedDate { get; set; }
    public DateTime? UpdatedDate { get; set; }
}

CompanyUpdateDto类

public class CompanyUpdateDto
{
    public int Id { get; set; }
    public string? Name { get; set; }
    public string? Description { get; set; }
    public DateTime? UpdatedDate { get; set; }
}

Program.cs配置

builder.Services.AddAutoMapper(typeof(AutoMapperProfile));

AutoMapper配置类(原配置)

public class AutoMapperProfile : Profile
{
    public AutoMapperProfile()
    {
        AllowNullCollections = true;

        #region Company DTO
        CreateMap<Company, CompanyDto>().ReverseMap();
        CreateMap<Company, CompanyCreateDto>().ReverseMap();
        //CreateMap<Company, CompanyUpdateDto>().ReverseMap();

        CreateMap<Company, CompanyUpdateDto>().ReverseMap().ForAllMembers(opts => opts.Condition((src, dest, srcMember) => srcMember != null));
        #endregion
    }
}

解决方案

核心问题分析

当前配置未生效的原因:

  1. 映射方向错误:更新场景是从CompanyUpdateDto映射到Company实体,原配置基于Company→CompanyUpdateDto反向生成,逻辑方向不匹配。
  2. 未处理可空值类型:比如DateTime?这类类型,仅判断srcMember != null无法区分“未设置值”和“有实际值”的情况。

全局配置实现

修改AutoMapper配置类,通过ForAllMaps全局针对所有命名包含UpdateDto的类生效,忽略源字段为空/未设置的情况:

public class AutoMapperProfile : Profile
{
    public AutoMapperProfile()
    {
        AllowNullCollections = true;

        // 全局配置:所有UpdateDto到实体的映射,忽略空值/未设置的字段
        ForAllMaps((map, opts) =>
        {
            if (map.SourceType.Name.EndsWith("UpdateDto"))
            {
                opts.ForAllMembers(memberOpts =>
                {
                    memberOpts.Condition((src, dest, srcMember) =>
                    {
                        // 排除null值
                        if (srcMember == null) return false;
                        // 处理可空值类型(如DateTime?),仅当有实际值时才映射
                        var nullableType = Nullable.GetUnderlyingType(srcMember.GetType());
                        if (nullableType != null)
                        {
                            return ((System.Nullable)srcMember).HasValue;
                        }
                        // 非可空值类型(如int Id)强制映射
                        return true;
                    });
                });
            }
        });

        #region Company DTO
        CreateMap<Company, CompanyDto>().ReverseMap();
        CreateMap<Company, CompanyCreateDto>().ReverseMap();
        // 仅配置UpdateDto到实体的映射,无需反向
        CreateMap<CompanyUpdateDto, Company>();
        #endregion
    }
}

业务逻辑配合

必须确保更新操作是将DTO映射到从数据库查询到的现有实体,而非创建新实体:

// 示例更新逻辑
public async Task UpdateCompany(CompanyUpdateDto dto)
{
    // 获取数据库中已存在的实体
    var existingCompany = await _context.Companies.FindAsync(dto.Id);
    if (existingCompany == null)
    {
        throw new KeyNotFoundException("Company not found");
    }
    // 将DTO的非空字段映射到现有实体
    _mapper.Map(dto, existingCompany);
    // 保存变更
    await _context.SaveChangesAsync();
}

额外说明

如果需要区分“用户主动提交null”和“未提交字段”,推荐使用JsonPatchDocument处理部分更新,此时无需AutoMapper空值忽略配置,因为Patch文档只会更新指定字段。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 01:15:31