【问题标题】:AutoMapper: How to map only matching property names and ignore all others?AutoMapper:如何仅映射匹配的属性名称并忽略所有其他名称?
【发布时间】:2018-10-15 01:44:23
【问题描述】:

我是 AutoMapper 的新手,使用的是 6.2.2 版。我正在尝试将视图模型映射到实体(也使用实体框架)。我只想更新视图模型和实体中存在的属性。该实体具有不属于源视图模型的其他导航属性和相关对象。我目前收到一个错误,即我在目标实体上有未映射的属性。我的视图模型和实体都有超过 40 个属性,所以我不想将每个属性都显式添加到地图中。

这是我的代码:

地图:

public static void RegisterMaps()
{
    AutoMapper.Mapper.Initialize(config =>
    {
                    config.CreateMap<EditApplicationViewModel, Application>();

    });

}

我也尝试了以下方法,但得到了同样的错误:

config.CreateMap<EditApplicationViewModel, Application>(MemberList.source);

控制器:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(EditApplicationViewModel viewModel)
{
    if (ModelState.IsValid)
    {
        Application application = _applicationService.GetById(viewModel.ApplicationId);

        application = Mapper.Map(viewModel, application);
    }
}

错误信息:

内部异常: H结果=-2146233088 Message= 找到未映射的成员。查看下面的类型和成员。添加自定义映射表达式,忽略,添加自定义 解析器,或修改源/目标类型对于没有匹配 构造函数,添加无参数 ctor,添加可选参数,或映射所有 构造函数参数 ==================================================== ======== 字符串 -> 用户(目标成员列表) System.String -> ..***.entities.User(目标成员列表)

未映射的属性:已删除 - 相关对象的很长列表 和目的地的属性

   Source=AutoMapper
   StackTrace:
        at lambda_method(Closure , EditApplicationViewModel , Application , ResolutionContext )

更新:

我也试过下面的地图。我没有收到任何错误,但没有在目标上更新任何源属性。

config.CreateMap<EditApplicationViewModel, Application>().ForAllOtherMembers(opts=>opts.Ignore());

【问题讨论】:

  • 该帖子的接受答案并不能解决我的问题。因此,我不认为这是重复的帖子。情况不同,AutoMapper的版本也不同。
  • 您是否尝试过来自 stackoverflow.com/questions/954480/automapper-ignore-the-rest/… 的 IgnoreUnmapped 扩展
  • @Rokal 情况有何不同? 6.2.2 > 5 并且该答案仍然有效。
  • 引用的答案处理忽略所有“未映射”属性(即,如果映射未在 CreateMap 中显式声明,则忽略它,即使源和目标中的属性名称匹配。这是不是我想要做的。

标签: c# automapper automapper-6


【解决方案1】:

我能够解决我的问题,它与忽略源和目标之间名称不匹配的属性无关。 AutoMapper 的默认行为似乎已经默认忽略了这些属性。

错误信息非常具有欺骗性:

  InnerException: 
       HResult=-2146233088
       Message=
Unmapped members were found. Review the types and members below.
Add a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type
For no matching constructor, add a no-arg ctor, add optional arguments, or map all of the constructor parameters
==========================================================
String -> User (Destination member list)
System.String -> ***.***.***.entities.User (Destination member list)

我的问题的实际原因是类型不匹配。我在视图模型中有一个名为 CreatedByUser 的字符串属性。我的实体上还有一个导航属性,名为 CreatedByUser,类型为 User。

我必须在 CreateMap 中明确忽略此属性。

 config.CreateMap<EditApplicationViewModel, Application>()
                    .ForMember(d => d.CreatedByUser, opt => opt.Ignore());

不需要其他指令来忽略源或目标上不存在的任何其他属性。

我再次收到错误消息“找到未映射的成员”。通过我关闭。实际的问题是类型不匹配。

【讨论】:

  • 听起来像一个错误。错误的异常消息。
  • 你说得对。在我的情况下:源属性是 Nullabe 布尔类型,而目标 - 仅布尔类型。
  • 虽然主题有所不同,但对我来说同样的问题:我有一个带有公共字符串 ID {get;set;} 的对象
【解决方案2】:

可能您在两个模型中的所有属性都没有相同的名称。对于不同的名称属性,您可以使用以下示例:

var source = new Source();

void ConfigureMap(IMappingOperationOptions<Source, Dest> opt) {
    opt.ConfigureMap()
       .ForMember(dest => dest.Value, m => m.MapFrom(src => src.Value))
};

var dest = Mapper.Map<Source, Dest>(source, ConfigureMap);

为每个新的属性名称不匹配定义新的.ForMember...

【讨论】:

  • 根据我的问题,我只想更新源和目标中具有相同名称的属性。我想忽略所有其他人。我不想做财产翻译。
  • 你试过像 IgnoreAllNonExisting github.com/AutoMapper/AutoMapper/issues/1386这样的扩展名
  • 引用的 GitHub 链接中提到的扩展方法自 5.0 版以来已失效,因为 expression.TypeMap 不再可用。我目前使用的是最新版本(6.2.2)。该链接没有给出可行的替代方案。
【解决方案3】:

您可以使用 IgnoreUnMapped() 函数。

          config.CreateMap<EditApplicationViewModel, Application>().IgnoreUnMapped();

【讨论】:

  • .IgnoreUpmapped() 方法不是 6.2.2 的一部分。我的理解是 config.CreateMap().ForAllOtherMembers(opts=>opts.Ignore()) 具有相同的目的。当我使用该地图时,我没有收到任何错误,但没有任何属性从源更新到目标。
  • Automapper 6.2.2版本不存在扩展方法
  • 那么我们在这里做什么呢?我正在尝试为 PUT 映射,但我没有每个道具,必须手动声明它们似乎很奇怪。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-31
  • 1970-01-01
  • 1970-01-01
  • 2017-02-19
  • 2019-02-22
  • 2019-04-12
  • 2022-09-24
相关资源
最近更新 更多