【问题标题】:Simple Example Subquery Linq简单示例子查询 Linq
【发布时间】:2014-10-10 21:02:08
【问题描述】:

T-SQL 查询

Select * from dbo.User_Users
Where UserID IN (Select UserID from Course_Enrollments)

LINQ to Entities 替代上述查询

var innerquery = from en in Course_Enrollments
select en.UserID;

var query = from u in User_Users
where innerquery.Contains(u.UserID)
select u;

* 上有很多复杂的子查询,我只想看一个简单的例子,说明如何通过 linq 完成一个简单的子查询。我就是这样做的,但它不好,因为它向数据库发送了 2 个查询。

【问题讨论】:

  • 您是否确认通过分析器发送了 2 个查询?通常,在枚举 IQueryable 或使用 ToList 或 FirstOrDefault 之类的东西之前,查询不会具体化。

标签: c# sql linq


【解决方案1】:

简单的答案是使用 "let" 关键字并生成一个支持主实体条件集的子查询。

var usersEnrolledInCourses = from u in User_Users
                                 let ces = from ce in Course_Enrollments
                                           select ce.UserID
                                 where ces.Contains(u.UserID)
                             select u;   

这将在 TSQL 中创建一个存在块,类似于

SELECT [Extent1].*
   FROM dbo.User_Users AS Extent1
   WHERE EXISTS (SELECT 1 AS [C1]
                     FROM dbo.Course_Enrollements AS Extent2
                     WHERE (Extent2.UserID = Extent1.UserId))

它与您的要求接近,通常会在 SQL Server 上创建相同的查询计划。

希望这会有所帮助!

【讨论】:

  • 当您有其他选项(例如 join 以提高性能)时,我不会进行内部子查询。对于用户中的每一行,您将执行一个完整的查询,然后包含。
【解决方案2】:
from u in User_Users
where u.Course_Enrollments.Any()
select u

如果您设置了外键。如果没有,你可以这样做

from u in User_Users
join cu in Course_Enrollments on u.UserId equals cu.UserId
select u

您还应该使用.Distinct() 调用来包装其中的任何一个

【讨论】:

  • 不幸的是,这个答案将导致 EF 将 TSQL 包装在查询周围的昂贵的 distinct 中。我建议不要这样做,尤其是在较大的数据集上。
  • @GregGrater,我不确定这个 Distinct 与主查询中每一行的子查询相比会有多昂贵,特别是对于更大的数据集。特别是在 Join 之后应该减少记录。