Вопрос
Дано , например , следующий набор данных:
new Entity { Id = 1, Group = 1, Value = "ABC", ... },
new Entity { Id = 2, Group = 1, Value = "DEF", ... },
new Entity { Id = 3, Group = 1, Value = "FGH", ... },
new Entity { Id = 4, Group = 1, Value = "LOP", ... },
new Entity { Id = 5, Group = 2, Value = "ALO", ... },
new Entity { Id = 6, Group = 2, Value = "PEO", ... },
new Entity { Id = 7, Group = 2, Value = "AHB", ... },
new Entity { Id = 8, Group = 2, Value = "DHB", ... },
new Entity { Id = 9, Group = 2, Value = "QPA", ... },
new Entity { Id = 10, Group = 2, Value = "LAN", ... },
// ... millions more records
как я могу сделать запрос, который эффективен (избегает проблемы с запросом N + 1) и дает мне первые 3 записи для каждого Group
, упорядоченного по Value
?
new Entity { Id = 1, Group = 1, Value = "ABC", ... },
new Entity { Id = 2, Group = 1, Value = "DEF", ... },
new Entity { Id = 3, Group = 1, Value = "FGH", ... },
new Entity { Id = 5, Group = 2, Value = "ALO", ... },
new Entity { Id = 7, Group = 2, Value = "AHB", ... },
new Entity { Id = 8, Group = 2, Value = "DHB", ... },
// ...
Что я пробовал?
В большинстве решений LINQ или Entity Framework для переполнения стека используется GroupBy
с Take
, который оценивается на стороне клиента (это означает, что все записи импортируются в память, а затем группировка происходит вне базы данных).
Я пробовал с:
var list = await _dbContext.Entities
.Select(x => new
{
OrderKey = _dbContext.Entities.Count(y =>
x.Group == y.Group
&& y.Value < x.Value),
Value = x,
})
.Where(x => x.OrderKey < 3)
.OrderBy(x => x.OrderKey)
.Select(x => x.Value)
.ToListAsync(cancellationToken);
но я уверен, что это неэффективно.
Бонусный вопрос
Как извлечь эту логику в метод расширения для IQueryable<T>
, который возвращает IQueryable<T>
?