.Net Core 3.1. Нужна вложенная группа По номенклатуре за день Количество Показать
Я хочу во вложенную группу по.
Я беру элементы заказа еженедельно и группирую их по имени типа, затем я хочу собрать дневную сумму продаж продукта с этим именем типа и получить результаты, как показано ниже.
Но я ошибаюсь в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."
}
1 ответ
Когда вы используете _context.OrderItems.GroupBy
, компилятор использует GroupBy
метод расширения из IQueryable
.
Когда вы запустите свою программу, среда выполнения попытается преобразовать выражения 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. Это означает, что все поля / столбцы, которые могут вам не понадобиться, также будут загружены в память. Если вы выполняете какие-либо операции с фильтрами, используяWhere
, вы можете попробовать выполнить их перед преобразованием запроса в IEnumerable
Я использую ToList()
выше, потому что ToListAsync()
недоступен для IEnumerable
.
Если вам действительно нужно использовать async, вы можете сделать это
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
обходной путь даст вам все.