【问题标题】:How to prevent AutoMapper from overwriting existing values on destination object?如何防止 AutoMapper 覆盖目标对象上的现有值?
【发布时间】:2021-12-05 12:28:59
【问题描述】:

我有以下实体和对应的视图模型

public class TopEntity
{
  public int Id { get; set; }

  public ICollection<BottomEntity> Bottoms { get; set; }
}

public class BottomEntity
{
  public int Id { get; set; }

  public int TopId { get; set; }
}

public class TopEntityViewModel
{
  public int Id { get; set; }

  public ICollection<BottomEntityViewModel> Bottoms { get; set; }
}

public class BottomEntityViewModel
{
  public int Id { get; set; }
}

我想将TopEntityViewModel 类型的实例映射到TopEntity 类型的实例,而不覆盖BottomEntity.TopId 上可能已经存在的任何值。

我已将 AutoMapper 配置如下:

var mapperConfig = new MapperConfiguration(exp =>
{
  exp.CreateMap<TopEntity, TopEntityViewModel>();

  exp.CreateMap<BottomEntity, BottomEntityViewModel>();

  exp.CreateMap<TopEntityViewModel, TopEntity>();

  exp.CreateMap<BottomEntityViewModel, BottomEntity>()
    .ForMember(dest => dest.TopId, opts => opts.Ignore());
});

我在映射过程中添加了.ForMember(dest =&gt; dest.TopId, opts =&gt; opts.Ignore()); 以忽略BottomEntity.TopId,认为它应该有助于保留现有值。

我正在像这样映射实例:

mapperConfig.AssertConfigurationIsValid();
            
var mapper = mapperConfig.CreateMapper();

var topEntity = new TopEntity
{
  Id = 45,
  Bottoms = new List<BottomEntity>
  {
    new BottomEntity
    {
      Id = 56,
      TopId = 45
    },
    new BottomEntity
    {
      Id = 57,
      TopId = 45
    }
  }
};

var topEntityVm = new TopEntityViewModel
{
  Id = 45,
  Bottoms = new List<BottomEntityViewModel>
  {
    new BottomEntityViewModel
    {
      Id = 56,
    },
    new BottomEntityViewModel
    {
      Id = 57
    }
  }
};

            
var updatedTopEntity = mapper.Map(topEntityVm, topEntity);

当我访问 updatedTopEntity.Bottoms[&lt;whatever&gt;].TopId 时,它总是设置为 0。 如果我在类上更新我对属性BottomEntity.TopId 的定义以具有像1000 这样的默认值,则在映射后我的所有updatedTopEntity.Bottoms[&lt;whatever&gt;].TopId 都设置为该默认值(示例中为1000)。
我检查了从 mapper.Map 返回的引用是否映射了原始引用并且它们确实如此。

如何防止 AutoMapper 删除现有实例上的任何现有值?

我正在使用 AutoMapper 10.1.1 和 .NET Core 5。You can try a working example here

【问题讨论】:

  • 你是否也检查过Bottoms是否是同一个集合实例?
  • 研究 AutoMapper.Collection.

标签: c# .net-core automapper automapper-10


【解决方案1】:

AutoMapper 说这个in the documentation

映射到现有集合时,首先清除目标集合。如果这不是您想要的,请查看 AutoMapper.Collection。

AutoMapper.Collection,根据文档,这样做:

添加将集合映射到现有集合的功能,而无需重新创建集合对象。
将根据用户定义的源集合和目标集合中集合的通用项类型之间的等效性,从预先存在的集合对象中添加/更新/删除项。

安装AutoMapper.Collection后我更新了AutoMapper配置如下:

var mapperConfig = new MapperConfiguration(exp =>
  {
    exp.AddCollectionMappers();
                
    exp.CreateMap<TopEntity, TopEntityViewModel>();

    exp.CreateMap<BottomEntity, BottomEntityViewModel>();

    exp.CreateMap<TopEntityViewModel, TopEntity>();

    exp.CreateMap<BottomEntityViewModel, BottomEntity>()
      .ForMember(dest => dest.TopId, opts => opts.Ignore())
      .EqualityComparison((src, dest) => src.Id == dest.Id);
  });

.EqualityComparison((src, dest) =&gt; src.Id == dest.Id); 行添加了 AutoMapper 将使用的相等比较,如下所示:

  • 如果 Id 匹配,则 AutoMapper 会将 BottomEntityViewModel 映射到 BottomEntity
  • 如果 BottomEntityViewModel 存在而 BottomEntity 不存在,则 AutoMapper 将从 BottomEntityViewModel 映射的新 BottomEntity 添加到集合中
  • 如果 BottomEntity 存在而 BottomEntityViewModel 不存在,则 AutoMapper 将从集合中删除 BottomEntity

AutoMapper.Collectionis described here的这种行为
工作示例:https://dotnetfiddle.net/tnaUjY

感谢Lucian Bargaoanu为我指出正确的方向

【讨论】:

    猜你喜欢
    • 2012-11-17
    • 1970-01-01
    • 1970-01-01
    • 2010-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-02
    • 1970-01-01
    相关资源
    最近更新 更多