如何在 DTO 中对数据库中的数据进行分组?

How do I group data from the database in a DTO?

如何将数据库中的数据分组到 dto 中?

例如我希望我的输出是这样的:

{
    id: "random-id-tst",
    years: [
        {
            year: 1,
            productIds: ['guid-id-1', 'guid-id-2'],
        },
        {
            year: 2,
            productIds: ['guid-id-3'],
        }
    ]
}

但是我很挣扎,尝试了很多东西,结果到了这个地步:

{
    id: "random-id-tst",
    years: [
        {
            year: 1,
            productIds: ['guid-id-1'],
        },
        {
            year: 1,
            productIds: ['guid-id-2'],
        },
        {
            year: 2,
            productIds: ['guid-id-3'],
        },
    ]
}
public class Order
{
    public Guid ID{ get; set; }

    public ICollection<OrderLine> OrderLines { get; set; }
}
public class OrderLine
{ 
    public Guid OrderID { get; set; }
    public Order Order { get; set; }
    public Guid ProductID { get; set; }
    public Product Product { get; set; }
    public int Year { get; set }
}
public class Product
{
    public Guid ID { get; set; }        
    public ICollection<OrderLine> OrderLines { get; set; }
}
 public class OrderDto
    {
        public Guid ID { get; set; }
        public IEnumerable<YearsDto> Years { get; set; }
    }
public class YearDto
{
    public int Year { get; set; }
    public ICollection<Guid> ProductIds { get; set; }
}

我尝试了很多东西,但每次都遇到不同的错误。

这是我所做的:

var orderLines = (await _context.OrderLine
    .Where(s => s.orderID == orderId)
    .ToListAsync()).GroupBy(ol => ol.Year);


var order = (await _context.Order
    .Where(order => order.ID == orderId)
    .Select(x =>
        new OrderDto()
        {
            ID = order.ID,
            Years = orderLines.Select(ss => new YearsDto()
            { 
                Year = 1,
            }),
        }
    ).FirstAsync());


return order;

如您所见,我硬编码了 Year 并且没有包含 productIds 因为出于某种原因我无法引用 ss.Yearss.Product,而且当我 运行 这个,它给了我一个错误: InvalidOperationException: variable '__Select_1' of type 'System.Collections.Generic.IEnumerable`1[YearsDto]' referenced from scope '', but it is not defined

有人可以指出正确的方向来解决我的问题吗?

在你的第一组中,你可能想要

var orderLines = (await _context.OrderLine
    .Where(s => s.orderID == orderId)
    .ToListAsync()).GroupBy(ol => ol.Year, (key, group) => new { Year = key, Items = group.ToList()});

这样,您的最终对象将是一个可枚举的匿名项目,包含属于那一年的 属性 Year 和 属性 Items

因此您的其余查询(只是为了使其编译并获取您需要的数据)可以转换为:

var order = (await _context.Order
    .Where(order => order.ID == orderId)
    .Select(x =>
        new OrderDto()
        {
            ID = order.ID,
            Years = orderLines.Select(ss => new YearsDto()
            { 
                Year = ss.Year,
                ProductsIds = ss.Items.Select(i => i.ProductID)
            }),
        }
    ).FirstAsync());


return order;

这段代码应该能得到你需要的结果:

            var order = _context.OrderLine
                .Include(o => o.OrderLines)
                .Where(s => s.Id == orderId)
                .First();

            var orderDto = new OrderDto()
            {
                ID = order.Id,
                Years = order.OrderLines.ToLookup(ol => ol.Year).Select(g => new YearDto() {Year = g.Key, ProductIds = g.ToList().Select(x => x.ProductID).ToList()})
            };

由于您不需要在 OrderDto 中添加任何额外数据,除了它的 ID(您已经拥有),您可以这样做:

var years  = ( await _context.OrderLine
    .Where(s => s.orderID == orderId)
    .Select( ol => new {ol.Year, ol.ProductID})
    .ToListAsync())
    .GroupBy(ol => ol.Year)
    .Select(g =>  new YearDto 
    { 
         Year = g.Key, 
         ProductIds = g.Select(i => i.ProductID).ToList() }
    )
    .ToList();
var orderDto = new OrderDto {ID = orderId; Years = years };

虽然会丢失db中订单存在的校验,但是可以单独查询