如何从平面实体映射到多个 DTO?
How to map from a flat entity to more than one DTO?
我希望在 C# .NET Core 中使用 AutoMapper 从一个已经扁平化的实体映射到一组嵌套的 DTO。此外,DTO 具有一对多关系,扁平实体隐藏在结构中。例如:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public int Price { get; set; }
public int Weight { get; set; }
}
public class ProductDto
{
public string Name { get; set; }
public IEnumerable<PriceDto> Prices { get; set; }
}
public class PriceDto
{
public int Price { get; set; }
public int Weight { get; set; }
}
我知道 AutoMapper 提供的 ReverseMap() 函数,但是考虑到我开始 一个扁平的实体,我不确定如何建立两者之间的关系ProductDto 和 PriceDto。
编辑:
这是我以 "Product" 的形式收到的一组扁平化数据示例。注意将需要的 ProductDto 和 PriceDto 之间的推断一对多关系。
+-----+-------+-------+--------+
| Id | Name | Price | Weight |
+-----+-------+-------+--------+
| 1 | "foo" | 8 | 12 |
| 2 | "foo" | 12 | 18 |
| 3 | "bar" | 3 | 1 |
| 4 | "bar" | 6 | 2 |
| ... | | | |
+-----+-------+-------+--------+
我会定义两个域配置文件。
一个用于 Product 到 ProductDto
CreateMap<Product, ProductDto>()
.ForMember(x => x.Id , opts => opts.Ignore())
.ForMember(x => x.Price , opts => opts.Ignore())
.ForMember(x => x.Weight , opts => opts.Ignore())
.ForMember(x => x.Name , opts => opts.MapFrom(y => y.Name));
还有一个用于 Product to PriceDto
CreateMap<Product, ProductDto>()
.ForMember(x => x.Id , opts => opts.Ignore())
.ForMember(x => x.Name , opts => opts.Ignore())
.ForMember(x => x.Price , opts => opts.MapFrom(y => y.Price ))
.ForMember(x => x.Weight , opts => opts.MapFrom(y => y.Weight ));
然后一次从同一个源映射到两个不同的目标。
您需要像下面这样实现自己的转换器:
ProductsConverter
public class ProductsConverter : ITypeConverter<List<Product>, List<ProductDto>>
{
public List<ProductDto> Convert(List<Product> source, List<ProductDto> destination, ResolutionContext context)
{
return source.GroupBy(p => p.Name)
.Select(r => new ProductDto
{
Name = r.Key,
Prices = source.Where(pp => pp.Name == r.Key)
.Select(rr => new PriceDto
{
Price = rr.Price,
Weight = rr.Weight
})
}).ToList();
}
}
ModelProfile
public class ModelProfile: Profile
{
public ModelProfile()
{
CreateMap<List<Product>, List<ProductDto>>()
.ConvertUsing<ProductsConverter>();
}
}
用例
public IActionResult Index()
{
List<Product> products= new List<Product>() {
new Product{ Id = 1, Name = "foo", Price = 8, Weight = 12},
new Product{ Id = 2, Name = "foo", Price = 12, Weight = 18},
new Product{ Id = 3, Name = "bar", Price = 3, Weight = 1},
new Product{ Id = 4, Name = "bar", Price = 6, Weight = 2},
};
var result = _mapper.Map<List<ProductDto>>(products);
return Ok(result);
}
我希望在 C# .NET Core 中使用 AutoMapper 从一个已经扁平化的实体映射到一组嵌套的 DTO。此外,DTO 具有一对多关系,扁平实体隐藏在结构中。例如:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public int Price { get; set; }
public int Weight { get; set; }
}
public class ProductDto
{
public string Name { get; set; }
public IEnumerable<PriceDto> Prices { get; set; }
}
public class PriceDto
{
public int Price { get; set; }
public int Weight { get; set; }
}
我知道 AutoMapper 提供的 ReverseMap() 函数,但是考虑到我开始 一个扁平的实体,我不确定如何建立两者之间的关系ProductDto 和 PriceDto。
编辑: 这是我以 "Product" 的形式收到的一组扁平化数据示例。注意将需要的 ProductDto 和 PriceDto 之间的推断一对多关系。
+-----+-------+-------+--------+
| Id | Name | Price | Weight |
+-----+-------+-------+--------+
| 1 | "foo" | 8 | 12 |
| 2 | "foo" | 12 | 18 |
| 3 | "bar" | 3 | 1 |
| 4 | "bar" | 6 | 2 |
| ... | | | |
+-----+-------+-------+--------+
我会定义两个域配置文件。 一个用于 Product 到 ProductDto
CreateMap<Product, ProductDto>()
.ForMember(x => x.Id , opts => opts.Ignore())
.ForMember(x => x.Price , opts => opts.Ignore())
.ForMember(x => x.Weight , opts => opts.Ignore())
.ForMember(x => x.Name , opts => opts.MapFrom(y => y.Name));
还有一个用于 Product to PriceDto
CreateMap<Product, ProductDto>()
.ForMember(x => x.Id , opts => opts.Ignore())
.ForMember(x => x.Name , opts => opts.Ignore())
.ForMember(x => x.Price , opts => opts.MapFrom(y => y.Price ))
.ForMember(x => x.Weight , opts => opts.MapFrom(y => y.Weight ));
然后一次从同一个源映射到两个不同的目标。
您需要像下面这样实现自己的转换器:
ProductsConverter
public class ProductsConverter : ITypeConverter<List<Product>, List<ProductDto>> { public List<ProductDto> Convert(List<Product> source, List<ProductDto> destination, ResolutionContext context) { return source.GroupBy(p => p.Name) .Select(r => new ProductDto { Name = r.Key, Prices = source.Where(pp => pp.Name == r.Key) .Select(rr => new PriceDto { Price = rr.Price, Weight = rr.Weight }) }).ToList(); } }
ModelProfile
public class ModelProfile: Profile { public ModelProfile() { CreateMap<List<Product>, List<ProductDto>>() .ConvertUsing<ProductsConverter>(); } }
用例
public IActionResult Index() { List<Product> products= new List<Product>() { new Product{ Id = 1, Name = "foo", Price = 8, Weight = 12}, new Product{ Id = 2, Name = "foo", Price = 12, Weight = 18}, new Product{ Id = 3, Name = "bar", Price = 3, Weight = 1}, new Product{ Id = 4, Name = "bar", Price = 6, Weight = 2}, }; var result = _mapper.Map<List<ProductDto>>(products); return Ok(result); }