将SQL转换为EF Linq

时间:2015-11-24 17:27:57

标签: c# entity-framework linq

我有以下查询:

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

4 个答案:

答案 0 :(得分:3)

直接翻译可能是这样的

array (size=2)
  0 => 
    array (size=2)
      'name' => string 'Name' (length=4)
      'value' => string '24' (length=2)
  1 => 
    array (size=2)
      'name' => string 'Name' (length=4)
      'value' => string '24' (length=2)

考虑到现在SQL var result = db.WorkItems.Any(wi => !wi.IsComplete && wi.TaskId == db.WorkItems .Where(x => x.WorkItemId == workItemId) .Select(x => x.TaskId) .FirstOrDefault())); =(subquery)IN (subquery)处理现代数据库的事实相同,您可以尝试这样做

EXISTS(subquery)

答案 1 :(得分:2)

事实证明我只需要从不同的角度解决问题。

我提出了三种具有不同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]

答案 2 :(得分:1)

您可以像这样使用Any()函数:

var result = Warehouse.WorkItems.Any(x => x.WorkItemId != null);

简而言之,您传递了您的条件,在这种情况下,检查您的收藏中的任何项目是否具有ID

变量result会告诉您集合中的所有项目是否都有ID。

这是一个有用的网页,可以帮助您开始使用LINQ:http://www.dotnetperls.com/linq

答案 3 :(得分:1)

原始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 );

再次抱歉让人感到困惑。