具有简单对象映射的Automapper未映射属性错误

时间:2019-01-30 07:30:16

标签: c# .net-core mapping entity-framework-core automapper

我需要将来自API的模型对象映射到DbContext上的实际实体对象。使用POST操作创建新的计算机对象时,将使用它。

和往常一样,我为源/目标对象创建了一个简单的映射。 在这种情况下,我们将源对象视为API模型,将目标对象视为实体。此外,模型仅包含实体属性的子集。

源/目的地类型

// Destination (entity on DbContext)
public class Machine
{
    public long Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public string MnmConfiguration { get; set; }
    public MachineBootStatus Status { get; set; }
    public long MachineDriverId { get; set; }
    public MachineDriver MachineDriver { get; set; }
    public string DriverConfiguration { get; set; }
    public string DriverStatus { get; set; }
}

// Source (from API controller)
public class MachineCreateModel
{
    public string Name { get; set; }
    public string Description { get; set; }
    public string MnmConfiguration { get; set; }
    public long MachineDriverId { get; set; }
}

映射配置

public class DomainProfile : Profile
{
    public DomainProfile()
    {
        //CreateMap<MachineCreateModel, Machine>();
        // Update 2019/01/30 with proposed solution
        CreateMap<MachineCreateModel, Machine>(MemberList.Source);
    }
}

我正在使用Unity DI容器,而AutoMapper的配置是这样的:

container = new UnityContainer();
// ... some other configurations...
container.RegisterType<IMapper, Mapper>(new InjectionConstructor(new MapperConfiguration(cfg => cfg.AddProfile<DomainProfile>())));

版本

使用AutoMapper v8.0.0。

预期行为

我希望获得一个没有错误的简单自动映射,因为我的源模型只是目标模型属性的一个子集,且名称相同。

实际行为

当我碰到以下代码行时,我得到有关未映射属性的错误:

Machine entity = Mapper.Map<Machine>(request.Machine);
[14:08:34.363 8 2e62361a INF] Creating new machine: TEST M1
[14:08:36.205 8 bd577466 ERR] An unhandled exception has occurred while executing the request.
AutoMapper.AutoMapperConfigurationException:
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
=================================================================================================
AutoMapper created this type map for you, but your types cannot be mapped using the current configuration.
MachineCreateModel -> Machine (Destination member list)
MyApplication.Dcs.Application.Models.MachineCreateModel -> MyApplication.Dcs.Domain.Entities.Machine (Destination member list)

Unmapped properties:
Id
Status
MachineDriver
DriverConfiguration
DriverStatus

   at AutoMapper.ConfigurationValidator.AssertConfigurationIsValid(IEnumerable`1 typeMaps)
   at lambda_method(Closure , MachineCreateModel , Machine , ResolutionContext )
   at lambda_method(Closure , Object , Object , ResolutionContext )
   at AutoMapper.Mapper.AutoMapper.IMapper.Map[TDestination](Object source)
   at MyApplication.Dcs.Application.Commands.MachineCreateCommandHandler.Handle(MachineCreateCommand request, CancellationToken cancellationToken) ..Commands\MachineCreateCommand.cs:line 28

注意

在我的解决方案中,我有很多项目,其中有3个项目正在使用AutoMapper(所有版本均相同)。有3个不同的DomainProfile.cs文件(每个项目1个)具有所需的映射。 在其他2个DomainProfile类中,我有一些手动映射(请参见下面的示例),因为我需要将具有意大利属性名称的对象“转换”为具有英语属性名称的另一个对象。因此,每个对象映射都有很多行,例如:

CreateMap<ArticleCreateUpdateModel, Articoli>()
    .ForMember(d => d.Categoria, opt => opt.MapFrom(src => src.Category))
    .ForMember(d => d.CodiceArticolo, opt => opt.MapFrom(src => src.Code))
    .ForMember(d => d.Descrizione, opt => opt.MapFrom(src => src.Description))
    .ForMember(d => d.Famiglia, opt => opt.MapFrom(src => src.Family))
    .ForMember(d => d.Note, opt => opt.MapFrom(src => src.Note))
    ...

我不知道在一个或多个DomainProfile类上使用那些手动成员映射是否使我不得不以某种方式始终解释所有后续映射,即使它们应该像这样简单例子。

1 个答案:

答案 0 :(得分:1)

默认情况下,AutoMapper会验证目标属性。由于目标类型中既没有匹配的属性,也没有ForMember的一系列属性的构造,因此会出现上述异常。

尝试验证源属性:

CreateMap<ArticleCreateUpdateModel, Articoli>(MemberList.Source)
    .ForMember(d => d.Categoria, opt => opt.MapFrom(src => src.Category))
    // ...

备注: 另一方面,我不得不提到,这是AutoMapper过度使用时的典型情况。除了琐碎的案例,我再也不会使用它了。

我不得不在一个项目中使用它超过一年,但实际上,这仅是使简单的事情变得比必要的复杂的好。某些FromDtoToDto [extension]方法更简单,更快,更容易调试,并且对代码更改反应更快。实际上,在不同的类布局或属性名称之间进行映射通常会产生与手动编写映射一样多的代码(甚至使用大量的lambda甚至会产生更多的代码)。另请参见this link