将SQL转换为EF Linq
本文关键字:EF Linq 转换 SQL | 更新日期: 2023-09-27 18:24:05
我有以下查询:
SELECT COUNT(1)
FROM Warehouse.WorkItems wi
WHERE wi.TaskId = (SELECT TaskId
FROM Warehouse.WorkItems
WHERE WorkItemId = @WorkItemId)
AND wi.IsComplete = 0;
由于我们使用的是EF,我希望能够使用Linq功能来生成这个查询。(我知道我可以给它一个这样的字符串查询,但出于重构的原因,我想使用EF+Linq为我生成查询。)
我真的不需要知道查询的结果。我只需要知道是否有结果。(使用Any()
将是完美的,但我无法获得它的编写代码。)
所以。。。基本上,我该如何将SQL查询写成LINQ查询?
编辑:表格结构
WorkItemId - int - Primary Key
TaskId - int - Foreign Key on Warehouse.Tasks
IsComplete - bool
JobId - int
UserName - string
ReportName - string
ReportCriteria - string
ReportId - int - Foreign Key on Warehouse.Reports
CreatedTime - DateTime
直接翻译可能类似于
var result = db.WorkItems.Any(wi =>
!wi.IsComplete && wi.TaskId == db.WorkItems
.Where(x => x.WorkItemId == workItemId)
.Select(x => x.TaskId)
.FirstOrDefault()));
考虑到当今现代数据库中SQL =(subquery)
、IN (subquery)
和EXISTS(subquery)
的处理方式相同,您可以尝试使用
var result = db.WorkItems.Any(wi =>
!wi.IsComplete && db.WorkItems.Any(x => x.WorkItemId == workItemId
&& x.TaskId == wi.TaskId));
事实证明,我只需要从不同的角度来处理这个问题。
我想出了大约三个不同Linq语法的解决方案:
全方法链:
var q1 = Warehouse.WorkItems
.Where(workItem => workItem.TaskId == (from wis in Warehouse.WorkItems
where wis.WorkItemId == workItemId
select wis.TaskId).First())
.Any(workItem => !workItem.IsComplete);
混合查询+方法链:
var q2 = Warehouse.WorkItems
.Where(workItem => workItem.TaskId == Warehouse.WorkItems
.Where(wis => wis.WorkItemId == workItemId)
.Select(wis => wis.TaskId)
.First())
.Any(workItem => !workItem.IsComplete);
完整查询:
var q3 = (from wi in Warehouse.WorkItems
where wi.TaskId == (from swi in Warehouse.WorkItems
where swi.WorkItemId == workItemId
select swi.TaskId).First()
where !wi.IsComplete
select 1).Any();
唯一的问题是它产生了一些真的劫持的SQL:
SELECT
(CASE
WHEN EXISTS(
SELECT NULL AS [EMPTY]
FROM [Warehouse].[WorkItems] AS [t0]
WHERE (NOT ([t0].[IsComplete] = 1)) AND ([t0].[TaskId] = ((
SELECT TOP (1) [t1].[TaskId]
FROM [Warehouse].[WorkItems] AS [t1]
WHERE [t1].[WorkItemId] = @p0
)))
) THEN 1
ELSE 0
END) AS [value]
您可以像这样使用Any()函数:
var result = Warehouse.WorkItems.Any(x => x.WorkItemId != null);
简言之,你通过了你的条件,在这种情况下,就是检查你收藏的物品是否有ID
变量result
将告诉您集合中的所有项目是否都有ID。
这里有一个有用的网页,可以帮助您开始使用LINQ:http://www.dotnetperls.com/linq
原始SQL中的子查询是无用的,因此不是Any()用法的好示例。它很简单:
SELECT COUNT(*)
FROM Warehouse.WorkItems wi
WHERE WorkItemId = @WorkItemId
AND wi.IsComplete = 0;
看起来,由于结果仅为0或1,猜测目的并基于如何编写Any(),它可能被写成:
SELECT CASE WHEN EXISTS ( SELECT *
FROM Warehouse.WorkItems wi
WHERE WorkItemId = @WorkItemId AND
wi.IsComplete = 0 ) THEN 1
ELSE 0
END;
那么使用Any():是有意义的
bool exists = db.WorkItems.Any( wi => wi.WorkItemId == workItemId & !wi.IsComplete );
编辑:对不起,我匆忙误读了原来的查询。以下是关于Linq用法的更新:
bool exists = db.WorkItems.Any( wi =>
db.WorkItems
.SingleOrDefault(wi.WorkItemId == workItemId).TaskId == wi.TaskId
&& !wi.IsComplete );
如果在原始SQL:中需要计数
var count = db.WorkItems.Count( wi =>
db.WorkItems
.SingleOrDefault(wi.WorkItemId == workItemId).TaskId == wi.TaskId
&& !wi.IsComplete );
再次对造成的混乱表示歉意。