.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 时,编译器使用 IQueryableGroupBy 扩展方法。

当您运行您的程序时,运行时间将尝试将 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 解决方法会给你带来任何好处。