自动映射 - 它是否只能映射源和目标对象中的现有属性?

Mis*_*pic 11 c# asp.net automapper

我有一个简单的更新功能:

public void Update(Users user)
{
    tblUserData userData = _context.tblUserDatas.Where(u => u.IDUSER == user.IDUSER).FirstOrDefault();
    if (userData != null)
    {
        Mapper.CreateMap<Users, tblUserData>();
        userData = Mapper.Map<Users, tblUserData>(user);
        _context.SaveChanges()
    }
}
Run Code Online (Sandbox Code Playgroud)

userData是一个EF实体,它的Entity Key属性被删除了,因为我相信它存在于目标对象中,但不存在于源对象中,因此它将使用其默认值进行映射(对于Entity Key,它是null )

所以,我的问题是,Automapper是否可以配置为仅尝试映射源对象和目标对象中存在的属性?我想要跳过实体键和导航属性之类的东西.

CSL*_*CSL 10

你可以明确地告诉AutoMapperIgnore某些属性,如果需要的是这样的:

Mapper.CreateMap<Users, tblUserData>()
        .ForMember(dest => dest.Id, opt => opt.Ignore());
Run Code Online (Sandbox Code Playgroud)

这意味着目标对象中的Id列始终保持不变.

您可以使用该Condition选项指定是否应用映射,具体取决于逻辑条件的结果,如下所示:

Mapper.CreateMap<Users, tblUserData>()
        .ForMember(dest => dest.Id, opt => opt.Condition(src=>src.Id.HasValue));
Run Code Online (Sandbox Code Playgroud)

要么

Mapper.CreateMap<Users, tblUserData>()
        .ForMember(dest => dest.Id, opt => opt.Condition(src=>src.Id != null));
Run Code Online (Sandbox Code Playgroud)

根据您的具体要求.

  • 我想要应用的规则是"当我的源属性存在于目标中,将源映射到目标,并忽略目标中的所有其他属性",但我相信你是正确的,因为我需要创建忽略条件如你所说. (5认同)
  • 是的,但是我必须为每个实体显式创建要忽略的属性列表.在我的情况下,对我来说最好的方法是有办法关闭"贪婪"的映射并让AutoMapper比较源和目标对象的属性,并仅映射两者中存在的属性.我没有在文档中看到任何这样的选项,所以我想我会问这里,但我不认为AutoMapper会这样做. (4认同)

小智 10

代替

userData = _mapper.Map<Users, tblUserData>(user);
Run Code Online (Sandbox Code Playgroud)

使用

 _mapper.Map(user, userData);
Run Code Online (Sandbox Code Playgroud)

前者创建一个新的 userData 对象,其中仅包含用户对象中可用的属性。后者使用用户对象中存在的属性覆盖现有 userData 对象的属性,同时保留其余部分。


hut*_*oid 5

您可以告诉AutoMapper忽略您不希望映射的字段,如下所示:

userData = Mapper.Map<Users, tblUserData>(user).ForMember(m => m.EntityKey, opt => opt.Ignore());
Run Code Online (Sandbox Code Playgroud)


Kha*_*qui 5

您可以通过创建一个小的扩展方法来忽略目标类型上不存在的所有属性来覆盖此行为。

public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
    var sourceType = typeof(TSource);
    var destinationType = typeof(TDestination);
    var existingMaps = Mapper.GetAllTypeMaps().First(x => x.SourceType.Equals(sourceType)
        && x.DestinationType.Equals(destinationType));
    foreach (var property in existingMaps.GetUnmappedPropertyNames())
    {
        expression.ForMember(property, opt => opt.Ignore());
    }
    return expression;
}
Run Code Online (Sandbox Code Playgroud)

然后可以按如下方式进行映射:

Mapper.CreateMap<SourceType, DestinationType>().IgnoreAllNonExisting();
Run Code Online (Sandbox Code Playgroud)

也可以根据您的需要自定义此方法,例如,通过专门忽略具有受保护或私有 setter 的属性。

  • `Mapper.GetAllTypeMaps()` 已过时使用 `Mapper.Configuration.GetAllTypeMaps()` [Mapper.GetAllTypeMaps() 已过时](https://github.com/AutoMapper/AutoMapper/issues/1252) (3认同)