AutoMapper:一对多 - >许多一对多

时间:2018-03-10 09:34:27

标签: c# entity-framework automapper entity-framework-core

我对AutoMapper相当新。我很难配置AutoMapper,以便能够将UserViewModel与多个TagViewModel映射到实体框架核心所需的多对多关系(RecipeEntity <-> TagEntity){{1是连接表。

数据对象:

UserAndTagEntity

测试示例:

public class TagEntity
{
    public string Name { get; set; }

    public virtual ICollection<UserAndTagEntity> UserAndTags { get; set; } = new List<UserAndTagEntity>();
}

public class UserEntity
{
    public string Name { get; set; }

    public virtual ICollection<UserAndTagEntity> UserAndTags { get; set; } = new List<UserAndTagEntity>();
}

public class UserAndTagEntity
{
    public int Id { get; set; }
    public virtual UserEntity User { get; set; }
    public virtual TagEntity Tag { get; set; }
}

public class UserViewModel
{
    public string Name { get; set; }

    public IList<TagViewModel> Tags { get; set; }
}

public class TagViewModel
{
    public string Name { get; set; }
}

这部分有效 - 我的问题是var config = new MapperConfiguration(cfg => { cfg.CreateMap<UserEntity, UserViewModel>() .ForMember( dto => dto.Tags, opt => opt.MapFrom(x => x.UserAndTags.Select(y => y.Tag))); cfg.CreateMap<UserViewModel, UserEntity>() .ForMember( dto => dto.UserAndTags, opt => opt.MapFrom(x => x.Tags)) .AfterMap((model, entity) => { foreach (var entityUserAndTag in entity.UserAndTags) { entityUserAndTag.User = entity; } }); cfg.CreateMap<TagViewModel, UserAndTagEntity>(); }); var user = new UserViewModel() { Name = "User", Tags = new List<TagViewModel> { new TagViewModel {Name = "Tag 1"}, new TagViewModel {Name = "Tag 2"}, new TagViewModel {Name = "Tag 3"}, new TagViewModel {Name = "Tag 4"}, } }; IMapper mapper = config.CreateMapper(); var map = mapper.Map<UserViewModel, UserEntity>(user); 上的Tag为空。

1 个答案:

答案 0 :(得分:2)

可以使用以下配置实现从UserViewModelUserEntity的映射:

CreateMap<UserViewModel, UserEntity>()
    // (1)
    .ForMember(entity => entity.UserAndTags, opt => opt.MapFrom(model => model.Tags))
    // (5)
    .AfterMap((model, entity) =>
    {
        foreach (var entityUserAndTag in entity.UserAndTags)
        {
            entityUserAndTag.User = entity;
        }
    });

// (2)
CreateMap<TagViewModel, UserAndTagEntity>()
    // (3)
    .ForMember(entity => entity.Tag, opt => opt.MapFrom(model => model));

// (4)
CreateMap<TagViewModel, TagEntity>();

<强>解释

需要第(1)行,因为目标和源属性名称不匹配,因此我们告诉AutoMapper将Tags的{​​{1}}属性映射到{ {1}}的{​​1}}属性。

请注意,映射不要求源属性和目标属性 types 匹配。如果他们不这样做(如本例所示),AutoMapper将使用单独的配置映射它们。

在我们的示例中,源属性类型为UserViewModel,目标属性类型为UserAndTags。忽略集合类型 - AutoMapper知道如何转换它们。它不知道和需要指定的是元素类型之间的映射。在我们的案例中,从UserEntityIList<TagViewModel>。因此需要映射(2)。

在映射(2)中,我们只有一个部分,所以我们使用(3)来指定 - 即我们将ICollection<UserAndTagEntity>映射到TagViewModel的{​​{1}}属性。类型再次不匹配,因此我们需要从UserAndTagEntityTagViewModel的映射(4)。

所有这些最终结果将是Tag实例,UserAndTagEntity集合填充了TagViewModel个具有正确TagEntity属性的实例。然后,步骤(5)用于填充这些实例的UserEntity属性。