我正在尝试编写一个 lambda 查询来检索所有可供出租或即将推出的产品(其中结束日期为 10 天后)。该查询将返回所有以前从未租用过的产品或已租用但即将可用的产品。
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Rent> Rents { get; set; }
}
public class Rent
{
public int Id { get; set; }
public Product Product { get; set; }
public int ProductId { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public DateTime CreationTime { get; set; }
}
通常 SQL 查询如下:
SELECT p.*, r1.*
FROM Products p
LEft JOIN Rents r1 ON (p.id = r1.ProductId)
LEFT OUTER JOIN Rents r2 ON (p.id = r2.ProductId AND
(r1.CreationTime < r2.CreationTime OR r1.CreationTime = r2.CreationTime AND r1.id < r2.id))
WHERE r2.id IS NULL AND (r1.EndDate is NULL OR r1.EndDate<='2018-06-24');
最佳答案
通常你会使用这样的东西:
from p in db.Products
let r = p.Rents.OrderByDescending(r => r.CreationTime).FirstOrDefault()
where r == null || r.EndDate <= DateTime.Now.Date.AddDays(10)
select new { p, r }
不幸的是,即使在目前最新的 EF Core 2.1 中,这也会导致 N + 1 次查询。
因此,您可以使用 SQL 查询的 LINQ 等效项。您应该使用 SQL NOT EXISTS
构造的 LINQ 等效项(即 !Any
)来代替第二个反连接:
from p in db.Products
from r in p.Rents.DefaultIfEmpty()
where r == null || (r.EndDate <= DateTime.Now.Date.AddDays(10) &&
!p.Rents.Any(r2 => r.CreationTime < r2.CreationTime || (r.CreationTime == r2.CreationTime && r.Id < r2.Id)))
select new { p, r }
这很好地转换为单个 SQL 查询。
关于c# - EF core 2.1 中具有 lambda 表达式的最大 n 个组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50858204/