在 EFCore 中的单个 LINQ 查询中获得 2 个前 5 个
Getting 2 Top 5 within a single LINQ query in EFCore
我要加载 10 个最新产品,其中 5 个属于 A 类,5 个属于 B 类。
所以结果包含类别 A 的 5 个最新产品和类别 B 的 5 个最新产品。
通常我可以使用这两个来完成:
var listA = await (
from p in db.Set<Product>()
where p.Category == "A"
orderby p.ProductDate descending
select p
).Take(5).ToListAsync();
var listB = await (
from p in db.Set<Product>()
where p.Category == "B"
orderby p.ProductDate descending
select p
).Take(5).ToListAsync();
var result = listA.Concat(listB);
但是如您所见,这段代码需要调用 2 次数据库。
如何仅使用 1 个数据库调用就可以获得结果?
在await
之前使用Concat
var listA = (
from p in db.Set<Product>()
where p.Category == "A"
orderby p.ProductDate descending
select p
).Take(5);
var listB = (
from p in db.Set<Product>()
where p.Category == "B"
orderby p.ProductDate descending
select p
).Take(5);
var result= await listA.Concat(listB).ToListAsync();
在 LINQ 查询中,像这样的东西应该可以工作:
var list = await(db.Product.Where(p => p.Category == "A" || p.Category == "B").OrderByDescending(p => p.ProductDate)
.ToList()
.GroupBy(p => p.Category)
.SelectMany(t => t.Select(b => b).Zip(Enumerable.Range(0, 5), (j, i) => j))).ToListAsync();
最近,EF 团队 confirmed 将向 EF Core 3 添加 UNION、CONCAT、EXCEPT 和 INTERSECT 的转换。
因此,如果您使用的是 EF Core 3 预览版,那么祝您好运,否则如果您想一次拍摄,就必须使用 RAW SQL 查询。
使用 EF Core 3.0.0-preview7.19362.6,您可以像这样编写它,它只生成一个查询并且工作得很好:
IQueryable<Product> topA = context.Products
.Where(p => p.Category == "A")
.OrderByDescending(x => x.ProductDate)
.Take(5);
IQueryable<Product> topB = context.Products
.Where(p => p.Category == "B")
.OrderByDescending(x => x.ProductDate)
.Take(5);
List<Product> result = await topA
.Concat(topB)
.OrderBy(p => p.Category)
.ToListAsync();
我要加载 10 个最新产品,其中 5 个属于 A 类,5 个属于 B 类。 所以结果包含类别 A 的 5 个最新产品和类别 B 的 5 个最新产品。
通常我可以使用这两个来完成:
var listA = await (
from p in db.Set<Product>()
where p.Category == "A"
orderby p.ProductDate descending
select p
).Take(5).ToListAsync();
var listB = await (
from p in db.Set<Product>()
where p.Category == "B"
orderby p.ProductDate descending
select p
).Take(5).ToListAsync();
var result = listA.Concat(listB);
但是如您所见,这段代码需要调用 2 次数据库。
如何仅使用 1 个数据库调用就可以获得结果?
在await
var listA = (
from p in db.Set<Product>()
where p.Category == "A"
orderby p.ProductDate descending
select p
).Take(5);
var listB = (
from p in db.Set<Product>()
where p.Category == "B"
orderby p.ProductDate descending
select p
).Take(5);
var result= await listA.Concat(listB).ToListAsync();
在 LINQ 查询中,像这样的东西应该可以工作:
var list = await(db.Product.Where(p => p.Category == "A" || p.Category == "B").OrderByDescending(p => p.ProductDate)
.ToList()
.GroupBy(p => p.Category)
.SelectMany(t => t.Select(b => b).Zip(Enumerable.Range(0, 5), (j, i) => j))).ToListAsync();
最近,EF 团队 confirmed 将向 EF Core 3 添加 UNION、CONCAT、EXCEPT 和 INTERSECT 的转换。 因此,如果您使用的是 EF Core 3 预览版,那么祝您好运,否则如果您想一次拍摄,就必须使用 RAW SQL 查询。
使用 EF Core 3.0.0-preview7.19362.6,您可以像这样编写它,它只生成一个查询并且工作得很好:
IQueryable<Product> topA = context.Products
.Where(p => p.Category == "A")
.OrderByDescending(x => x.ProductDate)
.Take(5);
IQueryable<Product> topB = context.Products
.Where(p => p.Category == "B")
.OrderByDescending(x => x.ProductDate)
.Take(5);
List<Product> result = await topA
.Concat(topB)
.OrderBy(p => p.Category)
.ToListAsync();