简体   繁体   English

将SQL转换为EF Linq

[英]Convert SQL to EF Linq

I have the following query: 我有以下查询:

SELECT COUNT(1)
FROM   Warehouse.WorkItems wi
WHERE  wi.TaskId = (SELECT TaskId
                    FROM   Warehouse.WorkItems
                    WHERE  WorkItemId = @WorkItemId)
  AND  wi.IsComplete = 0;

And since we are using EF, I'd like to be able to use the Linq functionality to generate this query. 由于我们使用的是EF,因此我希望能够使用Linq功能生成此查询。 (I know that I can give it a string query like this, but I would like to use EF+Linq to generate the query for me, for refactoring reasons.) (我知道我可以给它一个像这样的字符串查询,但我想使用EF + Linq为我生成查询,因为重构原因。)

I really don't need to know the results of the query. 我真的不需要知道查询的结果。 I just need to know if there are any results. 我只需要知道是否有任何结果。 (The use of an Any() would be perfect, but I can't get the write code for it.) (使用Any()会很完美,但我无法获得它的写代码。)

So... Basically, how do I write that SQL query as a LINQ query? 所以...基本上,我如何将该SQL查询编写为LINQ查询?

Edit: Table Structure 编辑:表格结构

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

The direct translation could be something like this 直接翻译可能是这样的

var result = db.WorkItems.Any(wi =>
    !wi.IsComplete && wi.TaskId == db.WorkItems
        .Where(x => x.WorkItemId == workItemId)
        .Select(x => x.TaskId)
        .FirstOrDefault()));

Taking into account the fact that SQL =(subquery) , IN (subquery) and EXISTS(subquery) in nowadays modern databases are handled identically, you can try this instead 考虑到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));

Turns out that I just needed to approach the problem from a different angle. 事实证明,我只需要从不同的角度来解决问题。

I came up with about three solutions with varying Linq syntaxes: 我提出了三种具有不同Linq语法的解决方案:

Full method chain: 完整方法链:

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

Mixed query + method chain: 混合查询+方法链:

var q2 = Warehouse.WorkItems
                  .Where(workItem => workItem.TaskId == Warehouse.WorkItems
                                                                 .Where(wis => wis.WorkItemId == workItemId)
                                                                 .Select(wis => wis.TaskId)
                                                                 .First())
                  .Any(workItem => !workItem.IsComplete);

Full query: 完整查询:

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();

The only problems with this is that it comes up with some really jacked up SQL: 唯一的问题是它提出了一些非常强大的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]

You can use the Any() function like so: 您可以像这样使用Any()函数:

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

In short, you pass in your condition, which in this case is checking whether or not any of the items in your collection have an ID 简而言之,您传递了您的条件,在这种情况下,检查您的集合中的任何项目是否具有ID

The variable result will tell you whether or not all items in your collection have ID's. 变量result将告诉您集合中的所有项目是否都具有ID。

Here's a helpful webpage to help you get started with LINQ: http://www.dotnetperls.com/linq 这是一个有用的网页,可以帮助您开始使用LINQ: http//www.dotnetperls.com/linq

Subquery in the original SQL was a useless one, thus not a good sample for Any() usage. 原始SQL中的子查询是无用的,因此不适合Any()用法。 It is simply: 它很简单:

SELECT COUNT(*)
FROM   Warehouse.WorkItems wi
WHERE  WorkItemId = @WorkItemId
  AND  wi.IsComplete = 0;

It looks like, since the result would be 0 or 1 only, guessing the purpose and based on seeking how to write Any(), it may be written as: 它看起来像,因为结果只有0或1,猜测目的并基于寻求如何编写Any(),它可以写成:

SELECT  CASE WHEN EXISTS ( SELECT *
                           FROM   Warehouse.WorkItems wi
                           WHERE  WorkItemId = @WorkItemId AND
                                  wi.IsComplete = 0 ) THEN 1
             ELSE 0
        END;

Then it makes sense to use Any(): 然后使用Any()是有意义的:

bool exists = db.WorkItems.Any( wi => wi.WorkItemId == workItemId & !wi.IsComplete );

EDIT: I misread the original query in a hurry, sorry. 编辑:我匆忙地误读了原始查询,抱歉。 Here is an update on the Linq usage: 以下是Linq用法的更新:

bool exists = db.WorkItems.Any( wi => 
   db.WorkItems
    .SingleOrDefault(wi.WorkItemId == workItemId).TaskId == wi.TaskId
  && !wi.IsComplete );

If the count was needed as in the original SQL: 如果原始SQL中需要计数:

var count = db.WorkItems.Count( wi => 
   db.WorkItems
    .SingleOrDefault(wi.WorkItemId == workItemId).TaskId == wi.TaskId
  && !wi.IsComplete );

Sorry again for the confusion. 对不起再次抱歉。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM