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

如何在C#中使用AutoMapper映射不同大小集合并保留目标元素

如何用AutoMapper实现源集合更新目标集合且保留目标集合原有元素?

问题场景

已知源集合(List<A>)包含2个元素,目标集合(List<B>)包含5个元素,调用mapper.Map(la, lb)后,目标集合被替换为仅包含2个元素,但期望实现按ID匹配更新对应元素,同时保留目标中未匹配的元素。

实体类定义

class A {
  public int Id;
  public string Name;
}

class B {
  public int Id;
  public string Name;
  public DateTime? DateOfBirth;
}

示例数据

var la = new List<A> {
  new A { Id = 1, Name = "A1" },
  new A { Id = 2, Name = "A2" }
};

var lb = new List<B> {
  new B { Id = 1, Name = "B1", DateOfBirth = new DateTime(2011, 2, 12) },
  new B { Id = 2, Name = "B2", DateOfBirth = new DateTime(2011, 3, 12) },
  new B { Id = 3, Name = "B3", DateOfBirth = new DateTime(2011, 4, 12) },
  new B { Id = 4, Name = "B4" },
  new B { Id = 5, Name = "B5" }
};

期望结果

映射后目标集合保留全部5个元素,仅更新ID匹配的元素:

{
  { 1, "A1", "2011-2-12" },
  { 2, "A2", "2011-3-12" },
  { 3, "B3", "2011-4-12" },
  { 4, "B4" },
  { 5, "B5" }
};

实际问题

调用mapper.Map(la, lb)后,目标集合仅保留前2个元素,丢失了ID为3、4、5的元素。


解决方案

AutoMapper默认的集合映射逻辑是直接替换整个目标集合,而非匹配更新元素。要实现需求,需指定集合映射的匹配规则,核心是用Id作为唯一匹配键。

方法1:通过自定义Profile配置映射规则

创建自定义Profile,配置单个对象映射规则,并自定义集合映射的转换逻辑,实现匹配更新:

public class MyProfile : Profile
{
    public MyProfile()
    {
        // 配置A到B的单个对象映射,保留目标的DateOfBirth字段
        CreateMap<A, B>()
            .ForMember(dest => dest.DateOfBirth, opt => opt.UseDestinationValue());
        
        // 配置集合映射:遍历源集合,匹配目标中同ID元素并更新,保留未匹配元素
        CreateMap<List<A>, List<B>>()
            .ConvertUsing((source, destination, context) =>
            {
                foreach (var sourceItem in source)
                {
                    var targetItem = destination.FirstOrDefault(b => b.Id == sourceItem.Id);
                    if (targetItem != null)
                    {
                        context.Mapper.Map(sourceItem, targetItem);
                    }
                }
                return destination;
            });
    }
}

方法2:手动遍历匹配更新

如果不想自定义Profile,也可以直接手动遍历源集合,匹配目标元素进行映射:

foreach (var a in la)
{
    var b = lb.FirstOrDefault(x => x.Id == a.Id);
    if (b != null)
    {
        mapper.Map(a, b);
    }
}

注意事项

  • 确保Id是唯一标识,用于准确匹配源和目标元素
  • 若需要新增源中有但目标中没有的元素,可在遍历逻辑中添加判断,未找到匹配项时向目标集合添加新元素
  • 单个对象映射时,若要保留目标的特定字段,需通过UseDestinationValue()或Ignore()配置

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 09:02:47