Automapper:映射多对多
Automapper: map many-to-many
我有以下型号:
public class Device
{
public string DeviceId { get; set; }
public string DeviceName { get; set; }
private ICollection<TagDevice> _tagDevices;
public virtual ICollection<TagDevice> TagDevices { get => _tagDevices ?? (_tagDevices = new List<TagDevice>()); protected set => _tagDevices = value; }
}
public class Tag : BaseEntity
{
public string Name { get; set; }
private ICollection<TagDevice> _tagDevices;
public virtual ICollection<TagDevice> TagDevices { get => _tagDevices ?? (_tagDevices = new List<TagDevice>()); protected set => _tagDevices = value; }
}
public class TagDevice
{
public int TagId { get; set; }
public string DeviceId { get; set; }
public virtual Tag Tag { get; set; }
public virtual Device Device { get; set; }
}
我有 DTO class:
public class TagDisplayDto
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime? UpdatedAt { get; set; }
public int TimesUsed { get; set; }
public int CarrierId { get; set; }
}
public class DeviceDisplayDto
{
public string DeviceId { get; set; }
public string DeviceName { get; set; }
public List<TagDisplayDto> Tags { get; set; }
}
现在,我想为 DeviceDisplayDto 创建映射并填充标签:
CreateMap<Device, DeviceDisplayDto>()
.ForMember(d => d.Tags, opt => opt.MapFrom(s => s.TagDevices...))
;
TagDevices
是集合不是Tag类型,集合的每个元素都有属性是Tag类型。如何创建?
您可以在 TagDevice
的集合上使用 Select()
将其转换为 TagDisplayDto
的列表:
CreateMap<Device, DeviceDisplayDto>()
.ForMember(deviceDisplayDto => deviceDisplayDto.Tags, options =>
options.MapFrom(device => device.TagDevices.Select(tagDevice => new TagDisplayDto
{
CarrierId = 123, // TODO
CreatedAt = DateTime.UtcNow, // TODO
Id = tagDevice.TagId,
Name = tagDevice.Tag.Name,
TimesUsed = 0, // TODO
UpdatedAt = DateTime.UtcNow, // TODO
}).ToList()));
我将一些属性标记为待办事项,因为我不知道您正在使用的整个模型并且缺少一些属性。您需要自行填写。至少该代码应该可以帮助您入门。
编辑#1
正如 Lucian 所建议的,更好的解决方案是充分利用 AutoMapper 功能。在两个模型之间创建映射:
- 从
Device
到 DeviceDisplayDto
- 从
TagDevice
到 TagDisplayDto
CreateMap<Device, DeviceDisplayDto>()
.ForMember(deviceDisplayDto => deviceDisplayDto.Tags, options =>
options.MapFrom(device => device.TagDevices));
CreateMap<TagDevice, TagDisplayDto>()
.ForMember(tagDisplayDto => tagDisplayDto.CarrierId, options =>
options.MapFrom(tagDevice => 123)) // TODO
.ForMember(tagDisplayDto => tagDisplayDto.CreatedAt, options =>
options.MapFrom(tagDevice => DateTime.UtcNow.AddDays(-60))) // TODO
.ForMember(tagDisplayDto => tagDisplayDto.Id, options =>
options.MapFrom(tagDevice => tagDevice.TagId))
.ForMember(tagDisplayDto => tagDisplayDto.Name, options =>
options.MapFrom(tagDevice => tagDevice.Tag.Name))
.ForMember(tagDisplayDto => tagDisplayDto.TimesUsed, options =>
options.MapFrom(tagDevice => 0)) // TODO
.ForMember(tagDisplayDto => tagDisplayDto.UpdatedAt, options =>
options.MapFrom(tagDevice => DateTime.UtcNow)); // TODO
这样,上面定义的映射逻辑就可以重用了。与我的第一个解决方案类似,您必须自己填写标有 TODO
的属性。
我有以下型号:
public class Device
{
public string DeviceId { get; set; }
public string DeviceName { get; set; }
private ICollection<TagDevice> _tagDevices;
public virtual ICollection<TagDevice> TagDevices { get => _tagDevices ?? (_tagDevices = new List<TagDevice>()); protected set => _tagDevices = value; }
}
public class Tag : BaseEntity
{
public string Name { get; set; }
private ICollection<TagDevice> _tagDevices;
public virtual ICollection<TagDevice> TagDevices { get => _tagDevices ?? (_tagDevices = new List<TagDevice>()); protected set => _tagDevices = value; }
}
public class TagDevice
{
public int TagId { get; set; }
public string DeviceId { get; set; }
public virtual Tag Tag { get; set; }
public virtual Device Device { get; set; }
}
我有 DTO class:
public class TagDisplayDto
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime? UpdatedAt { get; set; }
public int TimesUsed { get; set; }
public int CarrierId { get; set; }
}
public class DeviceDisplayDto
{
public string DeviceId { get; set; }
public string DeviceName { get; set; }
public List<TagDisplayDto> Tags { get; set; }
}
现在,我想为 DeviceDisplayDto 创建映射并填充标签:
CreateMap<Device, DeviceDisplayDto>()
.ForMember(d => d.Tags, opt => opt.MapFrom(s => s.TagDevices...))
;
TagDevices
是集合不是Tag类型,集合的每个元素都有属性是Tag类型。如何创建?
您可以在 TagDevice
的集合上使用 Select()
将其转换为 TagDisplayDto
的列表:
CreateMap<Device, DeviceDisplayDto>()
.ForMember(deviceDisplayDto => deviceDisplayDto.Tags, options =>
options.MapFrom(device => device.TagDevices.Select(tagDevice => new TagDisplayDto
{
CarrierId = 123, // TODO
CreatedAt = DateTime.UtcNow, // TODO
Id = tagDevice.TagId,
Name = tagDevice.Tag.Name,
TimesUsed = 0, // TODO
UpdatedAt = DateTime.UtcNow, // TODO
}).ToList()));
我将一些属性标记为待办事项,因为我不知道您正在使用的整个模型并且缺少一些属性。您需要自行填写。至少该代码应该可以帮助您入门。
编辑#1
正如 Lucian 所建议的,更好的解决方案是充分利用 AutoMapper 功能。在两个模型之间创建映射:
- 从
Device
到DeviceDisplayDto
- 从
TagDevice
到TagDisplayDto
CreateMap<Device, DeviceDisplayDto>()
.ForMember(deviceDisplayDto => deviceDisplayDto.Tags, options =>
options.MapFrom(device => device.TagDevices));
CreateMap<TagDevice, TagDisplayDto>()
.ForMember(tagDisplayDto => tagDisplayDto.CarrierId, options =>
options.MapFrom(tagDevice => 123)) // TODO
.ForMember(tagDisplayDto => tagDisplayDto.CreatedAt, options =>
options.MapFrom(tagDevice => DateTime.UtcNow.AddDays(-60))) // TODO
.ForMember(tagDisplayDto => tagDisplayDto.Id, options =>
options.MapFrom(tagDevice => tagDevice.TagId))
.ForMember(tagDisplayDto => tagDisplayDto.Name, options =>
options.MapFrom(tagDevice => tagDevice.Tag.Name))
.ForMember(tagDisplayDto => tagDisplayDto.TimesUsed, options =>
options.MapFrom(tagDevice => 0)) // TODO
.ForMember(tagDisplayDto => tagDisplayDto.UpdatedAt, options =>
options.MapFrom(tagDevice => DateTime.UtcNow)); // TODO
这样,上面定义的映射逻辑就可以重用了。与我的第一个解决方案类似,您必须自己填写标有 TODO
的属性。