AutoMapper - 映射多对多关系
AutoMapper - Map Many-to-Many Relationships
在我的 DAL 中,我有以下建立多对多关系的模型。
public class FamilyMember
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public ICollection<FamilyMemberPhone> FamilyMemberPhones { get; set; }
}
public class FamilyMemberPhone
{
public int FamilyMemberId { get; set; }
public int PhoneId { get; set; }
public FamilyMember FamilyMember { get; set; }
public Phone Phone { get; set; }
}
public class Phone : AuditableEntity
{
public int Id { get; set; }
public string PhoneNumber { get; set; }
public bool IsPreferred { get; set; }
public ICollection<FamilyMemberPhone> FamilyMemberPhones { get; set; }
}
在我的 DTO 中,我有以下 类
public class FamilyMemberDto
{
public int Id { get; set; }
public int FamilyId { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
public bool IsPrimary { get; set; }
[Required]
public List<Phone> FamilyMemberPhones { get; set; }
public string FullName => $" {FirstName} {LastName}";
}
public class PhoneDto
{
public int Id { get; set; }
public string PhoneNumber { get; set; }
public bool IsPreferred { get; set; }
public PhoneType PhoneType { get; set; }
}
我的映射配置如下所示:
CreateMap<Dal.Models.Phone, Dto.PhoneDto>().ReverseMap().IgnoreAuditableFields();
CreateMap<Dal.Models.FamilyMember, Dto.FamilyMemberDto>();
CreateMap<Dal.Models.FamilyMemberPhone, Dto.PhoneDto>()
.ForMember(d => d.Id, opt => opt.MapFrom(s => s.Id))
.ForMember(d => d.PhoneNumber, opt => opt.MapFrom(s => s.Phone.PhoneNumber))
.ForMember(d => d.PhoneType, opt => opt.MapFrom(s => s.Phone.PhoneType));
CreateMap<Dto.FamilyMemberDto, Dal.Models.FamilyMember>()
.AfterMap((s, d) =>
{
if (d.FamilyMemberPhones != null)
foreach (var fmp in d.FamilyMemberPhones)
fmp.Id = s.Id;
});
CreateMap<Dto.PhoneDto, Dal.Models.FamilyMemberPhone>()
.ForMember(d => d.PhoneId, opt => opt.MapFrom(s => s.Id));
我的单元测试是这样的:
var member = new Bll.Dto.FamilyMemberDto
{
FamilyId = 12,
FirstName = "Jane",
LastName = "Doe",
BirthDate = DateTime.Parse("11-01-1990"),
Email = "test@test.com",
FamilyMemberPhones = new List<Bll.Dto.PhoneDto>
{
new Bll.Dto.PhoneDto
{
PhoneNumber = "test",
IsPreferred = true,
},
new Bll.Dto.Phone
{
PhoneNumber = "hello",
IsPreferred = false,
}
}
};
await Manager.Save(member);
当我尝试使用 Mapper.Map<Dal.Models.FamilyMember>(dto)
将 DTO
映射到 Model
时,在 entity.FamilyMemberPhones
对象中,我看到集合中有两个项目。然而,深入挖掘集合,所有 Dal.Models.Phone
属性都是空的。
我做错了什么?
来自您代码的这个区域
CreateMap<Dto.FamilyMemberDto, Dal.Models.FamilyMember>()
.AfterMap((s, d) =>
{
if (d.FamilyMemberPhones != null)
foreach (var fmp in d.FamilyMemberPhones)
fmp.Id = s.Id;
});
您正在为在循环中创建的变量赋值。那是 fmp.Id = s.Id;
可能而不是 s.Id = fmp.Id;
甚至其他东西。因为那看起来不像你在那里做任何事情。
@formula12 的回答在我脑海中闪过一个念头。我需要考虑添加到家庭成员的每个 phone 号码。结果,每次我将 FamilyMemberDto
映射到 FamilyMember
时,我还需要考虑地图内部的 Phone
列表。
这是我的新映射配置文件:
CreateMap<Phone, Dto.PhoneDto>().ReverseMap().IgnoreAuditableFields();
CreateMap<FamilyMember, Dto.FamilyMemberDto>();
CreateMap<FamilyMemberPhone, Dto.PhoneDto>()
.ForMember(d => d.Id, opt => opt.MapFrom(s => s.Id))
.ForMember(d => d.PhoneNumber, opt => opt.MapFrom(s => s.Phone.PhoneNumber))
.ForMember(d => d.PhoneType, opt => opt.MapFrom(s => s.Phone.PhoneType));
CreateMap<Dto.FamilyMemberDto, FamilyMember>()
.AfterMap((s, d) =>
{
var memberPhones = new List<FamilyMemberPhone>();
foreach (var fmp in s.FamilyMemberPhones)
{
var phone = new FamilyMemberPhone
{
Phone = new Phone
{
Id = fmp.Id,
PhoneNumber = fmp.PhoneNumber,
PhoneType = fmp.PhoneType
}
};
memberPhones.Add(phone);
}
d.FamilyMemberPhones = memberPhones;
});
CreateMap<Dto.PhoneDto, FamilyMemberPhone>()
.ForMember(d => d.PhoneId, opt => opt.MapFrom(s => s.Id));
用例:
假设我的家庭成员在 FaimlyMemberDto.FamilyMemberPhones
中有三 (3) 个项目,这是一个 List<PhoneDto>
,在完成映射过程时,我的实体现在在 [=17= 中有 3 FamilyMemberPhone
个对象] 在 FamilyMember
对象中。在每一个里面,现在有一个映射到 PhoneDto
.
的 Phone
对象
在我的 DAL 中,我有以下建立多对多关系的模型。
public class FamilyMember
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public ICollection<FamilyMemberPhone> FamilyMemberPhones { get; set; }
}
public class FamilyMemberPhone
{
public int FamilyMemberId { get; set; }
public int PhoneId { get; set; }
public FamilyMember FamilyMember { get; set; }
public Phone Phone { get; set; }
}
public class Phone : AuditableEntity
{
public int Id { get; set; }
public string PhoneNumber { get; set; }
public bool IsPreferred { get; set; }
public ICollection<FamilyMemberPhone> FamilyMemberPhones { get; set; }
}
在我的 DTO 中,我有以下 类
public class FamilyMemberDto
{
public int Id { get; set; }
public int FamilyId { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
public bool IsPrimary { get; set; }
[Required]
public List<Phone> FamilyMemberPhones { get; set; }
public string FullName => $" {FirstName} {LastName}";
}
public class PhoneDto
{
public int Id { get; set; }
public string PhoneNumber { get; set; }
public bool IsPreferred { get; set; }
public PhoneType PhoneType { get; set; }
}
我的映射配置如下所示:
CreateMap<Dal.Models.Phone, Dto.PhoneDto>().ReverseMap().IgnoreAuditableFields();
CreateMap<Dal.Models.FamilyMember, Dto.FamilyMemberDto>();
CreateMap<Dal.Models.FamilyMemberPhone, Dto.PhoneDto>()
.ForMember(d => d.Id, opt => opt.MapFrom(s => s.Id))
.ForMember(d => d.PhoneNumber, opt => opt.MapFrom(s => s.Phone.PhoneNumber))
.ForMember(d => d.PhoneType, opt => opt.MapFrom(s => s.Phone.PhoneType));
CreateMap<Dto.FamilyMemberDto, Dal.Models.FamilyMember>()
.AfterMap((s, d) =>
{
if (d.FamilyMemberPhones != null)
foreach (var fmp in d.FamilyMemberPhones)
fmp.Id = s.Id;
});
CreateMap<Dto.PhoneDto, Dal.Models.FamilyMemberPhone>()
.ForMember(d => d.PhoneId, opt => opt.MapFrom(s => s.Id));
我的单元测试是这样的:
var member = new Bll.Dto.FamilyMemberDto
{
FamilyId = 12,
FirstName = "Jane",
LastName = "Doe",
BirthDate = DateTime.Parse("11-01-1990"),
Email = "test@test.com",
FamilyMemberPhones = new List<Bll.Dto.PhoneDto>
{
new Bll.Dto.PhoneDto
{
PhoneNumber = "test",
IsPreferred = true,
},
new Bll.Dto.Phone
{
PhoneNumber = "hello",
IsPreferred = false,
}
}
};
await Manager.Save(member);
当我尝试使用 Mapper.Map<Dal.Models.FamilyMember>(dto)
将 DTO
映射到 Model
时,在 entity.FamilyMemberPhones
对象中,我看到集合中有两个项目。然而,深入挖掘集合,所有 Dal.Models.Phone
属性都是空的。
我做错了什么?
来自您代码的这个区域
CreateMap<Dto.FamilyMemberDto, Dal.Models.FamilyMember>()
.AfterMap((s, d) =>
{
if (d.FamilyMemberPhones != null)
foreach (var fmp in d.FamilyMemberPhones)
fmp.Id = s.Id;
});
您正在为在循环中创建的变量赋值。那是 fmp.Id = s.Id;
可能而不是 s.Id = fmp.Id;
甚至其他东西。因为那看起来不像你在那里做任何事情。
@formula12 的回答在我脑海中闪过一个念头。我需要考虑添加到家庭成员的每个 phone 号码。结果,每次我将 FamilyMemberDto
映射到 FamilyMember
时,我还需要考虑地图内部的 Phone
列表。
这是我的新映射配置文件:
CreateMap<Phone, Dto.PhoneDto>().ReverseMap().IgnoreAuditableFields();
CreateMap<FamilyMember, Dto.FamilyMemberDto>();
CreateMap<FamilyMemberPhone, Dto.PhoneDto>()
.ForMember(d => d.Id, opt => opt.MapFrom(s => s.Id))
.ForMember(d => d.PhoneNumber, opt => opt.MapFrom(s => s.Phone.PhoneNumber))
.ForMember(d => d.PhoneType, opt => opt.MapFrom(s => s.Phone.PhoneType));
CreateMap<Dto.FamilyMemberDto, FamilyMember>()
.AfterMap((s, d) =>
{
var memberPhones = new List<FamilyMemberPhone>();
foreach (var fmp in s.FamilyMemberPhones)
{
var phone = new FamilyMemberPhone
{
Phone = new Phone
{
Id = fmp.Id,
PhoneNumber = fmp.PhoneNumber,
PhoneType = fmp.PhoneType
}
};
memberPhones.Add(phone);
}
d.FamilyMemberPhones = memberPhones;
});
CreateMap<Dto.PhoneDto, FamilyMemberPhone>()
.ForMember(d => d.PhoneId, opt => opt.MapFrom(s => s.Id));
用例:
假设我的家庭成员在 FaimlyMemberDto.FamilyMemberPhones
中有三 (3) 个项目,这是一个 List<PhoneDto>
,在完成映射过程时,我的实体现在在 [=17= 中有 3 FamilyMemberPhone
个对象] 在 FamilyMember
对象中。在每一个里面,现在有一个映射到 PhoneDto
.
Phone
对象