AutoMapper将多对多的关系融入集合中

时间:2012-08-02 17:44:08

标签: automapper

我正在尝试使用AutoMapper通过多对多表将实体映射到集合中。

我的域模型(实体框架)如下所示:

public class User
{
    public int UserID { get; set; }
    public string Name { get; set; }        
    public IList<UserCompany> UserCompanies { get; set; }
}

public class Company
{
    public int CompanyID { get; set; }
    public string Name { get; set; }
}

public class UserCompany
{
    public int UserCompanyID { get; set; }
    public int UserID { get; set; }
    public int CompanyID { get; set; }
}

我正在尝试映射到看起来像这样的类:

public class CompanyDTO
{
    public int CompanyID { get; set; }
    public string Name { get; set; }
}

public class UserDTO
{
    public int UserID { get; set; }
    public string Name { get; set; }
    public IList<CompanyDTO> Companies { get; set; }
}

我当前的映射配置如下所示:

Mapper.CreateMap<Company, CompanyDTO>(); //works no problem

Mapper.CreateMap<User, UserDTO>()
    .ForMember( dto => dto.Companies,
    opt => opt.MapFrom(x => Mapper.Map<IList<Company>, IList<CompanyDTO>>(x.UserCompanies.Select( y => y.Company ).ToList())));

断言配置有效返回true,但是当我尝试将User实际映射到UserDTO时,我得到:正文的签名和方法实现中的声明不匹配。

如果我使用AfterMap并手动将每个公司移到公司列表中,它会起作用,但似乎我应该能够在创建地图中处理它。

在我从DB获取单个用户的查询中,我包含了UserCompany.Company导航属性,我可以快速观察并看到有返回的内容。

1 个答案:

答案 0 :(得分:8)

您不需要在映射配置中使用显式映射。您应该可以执行以下操作:

Mapper.CreateMap<User, UserDTO>()
    .ForMember(dto => dto.Companies, opt => opt.MapFrom(x => x.UserCompanies));

您还需要为UserCompany定义映射:

Mapper.CreateMap<UserCompany, CompanyDTO>();

请注意,您的示例中没有CompanyDTO类,因此我无法确定实际的映射配置。

<强>更新

我认为你的用户实体需要一个IList而不仅仅是一个IList是有原因的。鉴于此,我相信您需要一个自定义解析器:https://github.com/AutoMapper/AutoMapper/wiki/Custom-value-resolvers

更新2

我很高兴你把它整理好了。为了完整性,下面是示例,您应该决定使用上述类的自定义ValueResolver。

Mapper.CreateMap<Company, CompanyDTO>();
Mapper.CreateMap<User, UserDTO>()
    .ForMember(dto => dto.Companies, opt => opt.ResolveUsing<CompanyResolver>());
Mapper.AssertConfigurationIsValid();

CompanyResolver类似于

public class CompanyResolver : ValueResolver<User, IList<CompanyDTO>>
{
    protected override IList<CompanyDTO> ResolveCore(User source)
    {
        return source.UserCompanies
            .Select(userCompany =>
                    Mapper.Map<Company, CompanyDTO>(companies.FirstOrDefault(x => x.CompanyID == userCompany.CompanyID)))
            .ToList();
    }
}