.Net 核心 3.1。每天需要Nested Group By item 数量显示
.Net Core 3.1. Need Nested Group By item daily Quantity show
我想嵌套分组依据。
我每周获取订单商品并按类型名称对它们进行分组,然后我想收集具有该类型名称的产品的每日销售额并获得如下结果。
但是我在Linq
查询中出错,无法解决原因。
return [
{
name: 'Shoes',
data: [502, 635, 809, 947, 1402, 3634, 5268],
},
{
name: 'Africa',
data: [106, 107, 111, 133, 221, 767, 1766],
},
{
name: 'tshirt',
data: [163, 203, 276, 408, 547, 729, 628],
},
{
name: 'pants',
data: [18, 31, 54, 156, 339, 818, 1201],
},
{
name: 'Oceania',
data: [2, 2, 2, 6, 13, 30, 46],
},
];
我的代码:
IReadOnlyList<OrderItemReportDto> query = await _context.OrderItems
.GroupBy(x => new { x.ItemOrdered.ProductType })
.Select(y => new OrderItemReportDto
{
Name = y.Key.ProductType,
Quantity = y.Sum(c => c.Quantity),
Count = y.GroupBy(x => x.CreatedTime.Date).Select(x => x.Sum(c => c.Quantity)).ToArray()
})
.ToListAsync();
return query;
OrderItemReportDto :
public class OrderItemReportDto
{
public string Name { get; set; }
public int Quantity { get; set; }
public int[] Count { get; set; }
}
Order Items :
public class OrderItem : BaseEntity
{
public OrderItem()
{
}
public OrderItem(OrderProductItem ıtemOrdered, decimal price, int quantity)
{
ItemOrdered = ıtemOrdered;
Price = price;
Quantity = quantity;
CreatedTime = DateTime.Now;
}
public OrderProductItem ItemOrdered { get; set; }
public decimal Price { get; set; }
public int Quantity { get; set; }
public DateTime CreatedTime
{
get
{
return this.dateCreated.HasValue
? this.dateCreated.Value
: DateTime.Now;
}
set { this.dateCreated = value; }
}
private DateTime? dateCreated = null;
}
但错误是:
{
"StatusCode": 500,
"Message": "The LINQ expression '(GroupByShaperExpression:\r\nKeySelector: new { ProductType = (t.ItemOrdered_ProductType) }, \r\nElementSelector:(EntityShaperExpression: \r\n EntityType: OrderItem\r\n ValueBufferExpression: \r\n (ProjectionBindingExpression: EmptyProjectionMember)\r\n IsNullable: False\r\n)\r\n)\r\n .GroupBy(x => x.CreatedTime.Date)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information."
}
当您使用 _context.OrderItems.GroupBy
时,编译器使用 IQueryable
的 GroupBy
扩展方法。
当您运行您的程序时,运行时间将尝试将 LINQ 表达式转换为 SQL 查询。但是,并非所有 LINQ 表达式都可以转换为 SQL 查询,因此会出现异常。
但是,如果您使用的是 IEnumerable
,运行 时间将不会生成 SQL 表达式。相反,它将加载内存中的所有项目,然后将 LINQ 表达式应用于这些集合。
试试改成
var query = context.OrderItems.AsEnumerable()
.GroupBy(x => new {x.ItemOrdered.ProductType})
.Select(y => new OrderItemReportDto
{
Name = y.Key.ProductType,
Quantity = y.Sum(c => c.Quantity),
Count = y.GroupBy(x => x.CreatedTime.Date).Select(x => x.Sum(c => c.Quantity)).ToArray()
})
.ToList();
现在请记住,这将是一项代价高昂的操作,因为您会将所有项目加载到内存中,然后应用 LINQ 子句。这意味着您可能不需要的所有 fields/column 也将加载到内存中。如果您正在使用 Where
执行任何筛选操作,您可以在将查询转换为 IEnumerable
之前尝试执行这些操作
我在上面使用 ToList()
,因为 ToListAsync()
不适用于 IEnumerable
。
如果你确实需要使用异步,你可以这样做
var query = context.OrderItems.AsEnumerable()
.GroupBy(x => new {x.ItemOrdered.ProductType})
.Select(y => new OrderItemReportDto
{
Name = y.Key.ProductType,
Quantity = y.Sum(c => c.Quantity),
Count = y.GroupBy(x => x.CreatedTime.Date).Select(x => x.Sum(c => c.Quantity)).ToArray()
}).AsQueryable()
.ToListAsync();
但是,我不认为这个 async
解决方法会给你带来任何好处。
我想嵌套分组依据。
我每周获取订单商品并按类型名称对它们进行分组,然后我想收集具有该类型名称的产品的每日销售额并获得如下结果。
但是我在Linq
查询中出错,无法解决原因。
return [
{
name: 'Shoes',
data: [502, 635, 809, 947, 1402, 3634, 5268],
},
{
name: 'Africa',
data: [106, 107, 111, 133, 221, 767, 1766],
},
{
name: 'tshirt',
data: [163, 203, 276, 408, 547, 729, 628],
},
{
name: 'pants',
data: [18, 31, 54, 156, 339, 818, 1201],
},
{
name: 'Oceania',
data: [2, 2, 2, 6, 13, 30, 46],
},
];
我的代码:
IReadOnlyList<OrderItemReportDto> query = await _context.OrderItems
.GroupBy(x => new { x.ItemOrdered.ProductType })
.Select(y => new OrderItemReportDto
{
Name = y.Key.ProductType,
Quantity = y.Sum(c => c.Quantity),
Count = y.GroupBy(x => x.CreatedTime.Date).Select(x => x.Sum(c => c.Quantity)).ToArray()
})
.ToListAsync();
return query;
OrderItemReportDto :
public class OrderItemReportDto
{
public string Name { get; set; }
public int Quantity { get; set; }
public int[] Count { get; set; }
}
Order Items :
public class OrderItem : BaseEntity
{
public OrderItem()
{
}
public OrderItem(OrderProductItem ıtemOrdered, decimal price, int quantity)
{
ItemOrdered = ıtemOrdered;
Price = price;
Quantity = quantity;
CreatedTime = DateTime.Now;
}
public OrderProductItem ItemOrdered { get; set; }
public decimal Price { get; set; }
public int Quantity { get; set; }
public DateTime CreatedTime
{
get
{
return this.dateCreated.HasValue
? this.dateCreated.Value
: DateTime.Now;
}
set { this.dateCreated = value; }
}
private DateTime? dateCreated = null;
}
但错误是:
{
"StatusCode": 500,
"Message": "The LINQ expression '(GroupByShaperExpression:\r\nKeySelector: new { ProductType = (t.ItemOrdered_ProductType) }, \r\nElementSelector:(EntityShaperExpression: \r\n EntityType: OrderItem\r\n ValueBufferExpression: \r\n (ProjectionBindingExpression: EmptyProjectionMember)\r\n IsNullable: False\r\n)\r\n)\r\n .GroupBy(x => x.CreatedTime.Date)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information."
}
当您使用 _context.OrderItems.GroupBy
时,编译器使用 IQueryable
的 GroupBy
扩展方法。
当您运行您的程序时,运行时间将尝试将 LINQ 表达式转换为 SQL 查询。但是,并非所有 LINQ 表达式都可以转换为 SQL 查询,因此会出现异常。
但是,如果您使用的是 IEnumerable
,运行 时间将不会生成 SQL 表达式。相反,它将加载内存中的所有项目,然后将 LINQ 表达式应用于这些集合。
试试改成
var query = context.OrderItems.AsEnumerable()
.GroupBy(x => new {x.ItemOrdered.ProductType})
.Select(y => new OrderItemReportDto
{
Name = y.Key.ProductType,
Quantity = y.Sum(c => c.Quantity),
Count = y.GroupBy(x => x.CreatedTime.Date).Select(x => x.Sum(c => c.Quantity)).ToArray()
})
.ToList();
现在请记住,这将是一项代价高昂的操作,因为您会将所有项目加载到内存中,然后应用 LINQ 子句。这意味着您可能不需要的所有 fields/column 也将加载到内存中。如果您正在使用 Where
执行任何筛选操作,您可以在将查询转换为 IEnumerable
我在上面使用 ToList()
,因为 ToListAsync()
不适用于 IEnumerable
。
如果你确实需要使用异步,你可以这样做
var query = context.OrderItems.AsEnumerable()
.GroupBy(x => new {x.ItemOrdered.ProductType})
.Select(y => new OrderItemReportDto
{
Name = y.Key.ProductType,
Quantity = y.Sum(c => c.Quantity),
Count = y.GroupBy(x => x.CreatedTime.Date).Select(x => x.Sum(c => c.Quantity)).ToArray()
}).AsQueryable()
.ToListAsync();
但是,我不认为这个 async
解决方法会给你带来任何好处。