Linq-to-sql 使用 GroupBy 并返回满足条件的记录
Posted
技术标签:
【中文标题】Linq-to-sql 使用 GroupBy 并返回满足条件的记录【英文标题】:Linq-to-sql using GroupBy and return record satisfying condition 【发布时间】:2022-01-13 21:15:39 【问题描述】:我有一个查询,我将提供它的相关部分
IQueryable<a> query;
query.Where(dbEntry => dbEntry.ConditionId == id)
.Where(dbEntry => dbEntry.PharmacyStockBBD.Value > NO_BEFORE_THAN)
.GroupBy(dbEntry => dbEntry.ProductId, pair => pair, (_e1, _e2) => new
ProductId = _e1,
Entry = _e2.OrderBy(pair => pair.PharmacyStockBBD).First()
)
.ToListAsync();
我来了
System.InvalidOperationException: The LINQ expression '(GroupByShaperExpression: KeySelector: (p.Id), ElementSelector:new PharmacyStockId = (ProjectionBindingExpression: PharmacyStockId), PharmacyStockBBD = (ProjectionBindingExpression: PharmacyStockBBD), ProductId = (ProjectionBindingExpression: ProductId), ProductName = (ProjectionBindingExpression: ProductName), ChildProductId = (ProjectionBindingExpression: ChildProductId), IcnId = (ProjectionBindingExpression: IcnId), IcnName = (ProjectionBindingExpression: IcnName), PharmacyStock_ProductBoxes = (ProjectionBindingExpression: PharmacyStock_ProductBoxes), ..... ) .OrderBy(pair => pair.PharmacyStockBBD)' could not be translated. Either rewrite the query in a form that can be translated,
或通过插入调用显式切换到客户端评估 AsEnumerable()、AsAsyncEnumerable()、ToList() 或 ToListAsync()。见https://go.microsoft.com/fwlink/?linkid=2101038 更多信息。
我要做的是按 ProductId 分组,但只获取 PharmacyStockBBD 为 Min 的记录。
我已经走了
Entry = _e2.Min(pair => pair.PharmacyStockBBD)
可行,但我需要整个 _e2。
我还知道 GroupBy 将在 sql 引擎 (MSSSQL) 上执行,我也知道它需要一些聚合函数,但我需要 PharmacyStockBBD
最小的整个记录集。
【问题讨论】:
GroupBy 将在 sql 引擎上执行实际上该特定查询不会在数据库中执行,这就是错误的症结.. 你能提供更多的上下文吗?也许我可以使用一个例子? 这个错误的意思是“你写的查询不能被翻译成sql并在db服务器上运行,所以你的选择是用可以翻译成sql的方式重写它,或者下载所有的数据从 db 服务器出来,然后 LINQ 将遍历它并在 c# 中进行分组”。在过去,后者是自动发生的,这是相当可怕的 顺便说一句,这不是 linq-to-sql;这是 EF 前身的名称;这是英孚 【参考方案1】:我认为最有效的方法是使用原始 sql;
context.YourTable.FromSqlInterpolated(@"
SELECT *
FROM
(
SELECT *, ROW_NUMBER() OVER(PARTITION BY ProductId ORDER BY PharmacyStockBBD) rn
FROM YourTable
WHERE
PharmacyStockId > NO_BEFORE_THAN
) x
WHERE rn = 1")
您可以在此基础上进行撰写(包括更多表格等
我不确定您要在哪里进行 ConditionId 检查;它的确有所作为。如果您在内部查询中执行此操作,那么您将找到该条件的所有产品,然后从 1 开始对它们进行编号并找到该条件下的最小产品。如果您在外部查询中执行此操作,您将找到所有产品,无论条件如何,对它们进行编号,然后丢弃所有不在条件中的产品。你把它放在哪里取决于第一个产品是否会处于你想要的状态
本质上,你是要“过滤条件,然后取第一个” -> 把它放在里面 where ,还是要“取所有第一个,然后过滤它们作为条件” -> 把它放在里面外面的地方
【讨论】:
以上是关于Linq-to-sql 使用 GroupBy 并返回满足条件的记录的主要内容,如果未能解决你的问题,请参考以下文章