C# 自动映射:一对多->;多对多

C# 自动映射:一对多->;多对多,c#,entity-framework,automapper,entity-framework-core,C#,Entity Framework,Automapper,Entity Framework Core,我是汽车制造商的新手。我很难将AutoMapper配置为能够将具有多个TagViewModel的UserViewModel映射到多对多关系(RecipeEntity TagEntity)中,这是实体框架核心所需的,UserAndTagEntity是连接表 数据对象: public class TagEntity { public string Name { get; set; } public virtual ICollection<UserAndTagEntity>

我是汽车制造商的新手。我很难将AutoMapper配置为能够将具有多个
TagViewModel
UserViewModel
映射到多对多关系(
RecipeEntity TagEntity
)中,这是实体框架核心所需的,
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; }
}
公共类标记实体
{
公共字符串名称{get;set;}
公共虚拟ICollection UserAndTags{get;set;}=new List();
}
公共类用户实体
{
公共字符串名称{get;set;}
公共虚拟ICollection UserAndTags{get;set;}=new List();
}
公共类UserAndTagEntity
{
公共int Id{get;set;}
公共虚拟用户实体用户{get;set;}
公共虚拟标记实体标记{get;set;}
}
公共类UserViewModel
{
公共字符串名称{get;set;}
公共IList标记{get;set;}
}
公共类TagViewModel
{
公共字符串名称{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);
var config=new-MapperConfiguration(cfg=>{
cfg.CreateMap()
福门博先生(
dto=>dto.Tags,
opt=>opt.MapFrom(x=>x.UserAndTags.Select(y=>y.Tag));
cfg.CreateMap()
福门博先生(
dto=>dto.UserAndTags,
opt=>opt.MapFrom(x=>x.Tags))
.AfterMap((模型、实体)=>
{
foreach(entity.UserAndTags中的var entityUserAndTag)
{
entityUserAndTag.User=实体;
}
});
CreateMap();
});
var user=new UserViewModel()
{
Name=“User”,
标签=新列表
{
新的TagViewModel{Name=“Tag 1”},
新的TagViewModel{Name=“Tag 2”},
新的TagViewModel{Name=“Tag 3”},
新的TagViewModel{Name=“Tag 4”},
}
};
IMapper mapper=config.CreateMapper();
var map=mapper.map(用户);

这在一定程度上起作用-我遇到的问题是
UserAndTagEntity
上的
Tag
为空。

可以通过以下配置实现从
UserViewModel
UserEntity
的映射:

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>();
CreateMap()
// (1)
.ForMember(entity=>entity.UserAndTags,opt=>opt.MapFrom(model=>model.Tags))
// (5)
.AfterMap((模型、实体)=>
{
foreach(entity.UserAndTags中的var entityUserAndTag)
{
entityUserAndTag.User=实体;
}
});
// (2)
CreateMap()
// (3)
.ForMember(entity=>entity.Tag,opt=>opt.MapFrom(model=>model));
// (4)
CreateMap();
说明:

需要行(1),因为目标和源属性名称不匹配,所以我们只需要告诉AutoMapper将
UserViewModel的
Tags
属性映射到
UserEntity的
UserAndTags
属性

请注意,映射不要求源和目标属性类型匹配。如果它们没有(如本例中所示),AutoMapper将使用单独的配置映射它们

在我们的例子中,源属性类型是
IList
,目标属性类型是
ICollection
。忽略集合类型-AutoMapper知道如何转换它们。它不知道并且需要指定的是元素类型之间的映射。在我们的例子中,从
TagViewModel
UserAndTagEntity
。因此需要映射(2)

在映射(2)中,我们只有一个部分,因此我们使用(3)指定-即,我们将
TagViewModel
映射到
UserAndTagEntity
Tag
属性。同样,类型不匹配,因此我们需要从
TagViewModel
TagEntity
的映射(4)


最后的结果将是
UserEntity
实例和
UserAndTags
集合,集合中填充了
UserAndTagEntity
实例和正确的
Tag
属性。然后使用步骤(5)填充这些实例的
User
属性。

可以通过以下配置实现从
UserViewModel
UserEntity
的映射:

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>();
CreateMap()
// (1)
.ForMember(entity=>entity.UserAndTags,opt=>opt.MapFrom(model=>model.Tags))
// (5)
.AfterMap((模型、实体)=>
{
foreach(entity.UserAndTags中的var entityUserAndTag)
{
entityUserAndTag.User=实体;
}
});
// (2)
CreateMap()
// (3)
.ForMember(entity=>entity.Tag,opt=>opt.MapFrom(model=>model));
// (4)
CreateMap();
说明:

需要行(1),因为目标和源属性名称不匹配,所以我们只需要告诉AutoMapper将
UserViewModel的
Tags
属性映射到
UserEntity的
UserAndTags
属性

请注意,映射不要求源和目标属性类型匹配。如果它们没有(如本例中所示),AutoMapper将使用单独的配置映射它们

在我们的例子中,源属性类型是
IList
,目标属性类型是
ICollection
。忽略集合类型-AutoMapper知道如何转换它们。它不知道并且需要指定的是元素类型之间的映射。在我们的例子中,从
TagViewModel
UserAndTagEntity
。因此需要映射(2)

在映射(2)中,我们只有一个部分,因此我们使用(3)指定-即,我们将
TagViewModel
映射到
UserAndTagEntity
Tag
属性。同样,类型不匹配,因此我们需要从
TagViewModel
TagEntity
的映射(4)

最后的结果将是
UserEntity
实例和
UserAndTags
集合,集合中填充了
UserAndTagEntity
实例和正确的
Tag