AutoMapper:如何仅映射匹配的属性名称并忽略所有其他属性?

9
我是一名有用的助手,会为你翻译文本。
我是AutoMapper新手,正在使用版本6.2.2。 我试图将视图模型映射到实体(也使用Entity Framework)。 我只想更新视图模型和实体中都存在的属性。 实体具有其他导航属性和相关对象,这些都不是源视图模型的一部分。 我当前收到一个错误,指出目标实体上存在未映射的属性。 我的视图模型和实体都有超过40个属性,因此我不想将每个属性都明确添加到映射中。
这是我的代码:
映射:
public static void RegisterMaps()
{
    AutoMapper.Mapper.Initialize(config =>
    {
                    config.CreateMap<EditApplicationViewModel, Application>();

    });

}

我也尝试了以下方法,但是出现了相同的错误:
config.CreateMap<EditApplicationViewModel, Application>(MemberList.source);

Controller:

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

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

错误信息:

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)

Unmapped properties: removed - a very long list of related objects and properties on the destination

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

更新:

我还尝试了以下地图。虽然没有收到任何错误信息,但目标上的源属性都没有更新。

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

1
可能是[Automapper v5忽略未映射属性]的重复问题(https://dev59.com/CZvga4cB1Zd3GeqP3IXX)。 - Michael Freidgeim
那篇帖子的被接受答案并没有解决我的问题。因此,我不认为这是一个重复的帖子。情况不同,AutoMapper的版本也不同。 - Rokal
你尝试过从 https://dev59.com/3nNA5IYBdhLWcg3wdthd#38073718 使用 IgnoreUnmapped 扩展吗? - Michael Freidgeim
@Rokal 这个案例有什么不同吗?6.2.2 > 5,这个答案仍然有效。 - aaron
所引用的答案处理了忽略所有“未映射”的属性(即,如果在CreateMap中没有明确声明映射,则忽略它,即使源和目标中的属性名称匹配)。这不是我试图做的。 - Rokal
@Rokal - "None of the source properties are being updated on the destination" = "目标上没有任何源属性被更新" - N73k
3个回答

11

我已经解决了我的问题,这与忽略源和目标之间名称不匹配的属性无关。似乎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());

没有必要使用其他指令来忽略源或目标中不存在的任何其他属性。

再次,我收到的错误信息“找到未映射的成员”让我感到困惑。实际问题是类型不匹配。


听起来像是一个 bug。异常信息不太好。 - Jeremy Holovacs
你说得没错。在我的情况下:源属性是可空布尔类型,而目标属性只是布尔类型。 - rock_walker
虽然有所不同,但我也遇到了同样的问题:我有一个对象,其中包含公共字符串Id {get;set;}。 - ubienewbie

0

您可以使用 IgnoreUnMapped() 函数。

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

5
.IgnoreUpmapped() 方法不属于6.2.2版本。我的理解是,config.CreateMap <EditApplicationViewModel,Application>().ForAllOtherMembers(opts=>opts.Ignore()) 可以达到相同的目的。当我使用该映射时,没有出现任何错误,但源属性未更新到目标属性。 - Rokal
Automapper的6.2.2版本中不存在扩展方法。 - rock_walker
1
那么我们在这里要做什么?我正在尝试为PUT进行映射,但我没有每个属性,手动声明它们似乎很奇怪。 - JDPeckham

0

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

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...


根据我的问题,我只想更新源和目标中名称相同的属性。我希望忽略所有其他属性。我不想进行属性翻译。 - Rokal
你尝试过使用 IgnoreAllNonExisting 这样的扩展吗?https://github.com/AutoMapper/AutoMapper/issues/1386 - Alen
1
引用的 GitHub 链接中提到的扩展方法自版本 5.0 以来就不再可用,因为 expression.TypeMap 不再可用。我目前使用的是最新版本(6.2.2)。该链接没有提供可行的替代方案。 - Rokal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接