当前位置:  开发笔记 > 编程语言 > 正文

如何在LINQ中执行子查询?

如何解决《如何在LINQ中执行子查询?》经验,为你挑选了3个好方法。

这是我试图转换为LINQ的查询示例:

SELECT *
FROM Users
WHERE Users.lastname LIKE '%fra%'
    AND Users.Id IN (
         SELECT UserId 
         FROM CompanyRolesToUsers 
         WHERE CompanyRoleId in (2,3,4) )

CompanyRolesToUsers和之间存在FK关系Users,但它是多对多的关系,并且CompanyRolesToUsers是联结表.

我们已经构建了大部分网站,并且我们已经通过使用PredicateExtensions类构建Expressions来完成大部分过滤工作.

简单过滤器的代码如下所示:

 if (!string.IsNullOrEmpty(TextBoxLastName.Text))
 {
     predicateAnd = predicateAnd.And(c => c.LastName.Contains(
                                     TextBoxLastName.Text.Trim()));
 }

e.Result = context.Users.Where(predicateAnd);

我正在尝试在另一个表中为子选择添加谓词.(CompanyRolesToUsers)

我希望能够添加的内容是:

int[] selectedRoles = GetSelectedRoles();
if( selectedRoles.Length > 0 )
{
    //somehow only select the userid from here ???:
    var subquery = from u in CompanyRolesToUsers
                   where u.RoleID in selectedRoles
                   select u.UserId;

    //somehow transform this into an Expression ???:
    var subExpression = Expression.Invoke(subquery);

    //and add it on to the existing expressions ???:
    predicateAnd = predicateAnd.And(subExpression);
}

有没有办法做到这一点?这很令人沮丧,因为我可以轻松编写存储过程,但我是这个LINQ的新手,我有一个截止日期.我找不到匹配的例子,但我确定它在某处.



1> Amy B..:

这是给你的子查询!

List IdsToFind = new List() {2, 3, 4};

db.Users
.Where(u => SqlMethods.Like(u.LastName, "%fra%"))
.Where(u =>
    db.CompanyRolesToUsers
    .Where(crtu => IdsToFind.Contains(crtu.CompanyRoleId))
    .Select(crtu =>  crtu.UserId)
    .Contains(u.Id)
)

关于这部分问题:

predicateAnd = predicateAnd.And(c => c.LastName.Contains(
                                TextBoxLastName.Text.Trim()));

我强烈建议在创建查询之前从文本框中提取字符串.

string searchString = TextBoxLastName.Text.Trim();
predicateAnd = predicateAnd.And(c => c.LastName.Contains( searchString));

您希望对发送到数据库的内容保持良好的控制.在原始代码中,一个可能的读取是未修剪的字符串被发送到数据库进行修剪 - 这对数据库来说不是一件好事.


感谢您提供有用的代码.这无疑表明事物可以链接在一起.在将它交给Linq之前你也可能正确执行字符串操作,将事情分开肯定不会有害.

2> TheSoftwareJ..:

此语句不需要子查询,更好地编写为

select u.* 
from Users u, CompanyRolesToUsers c
where u.Id = c.UserId        --join just specified here, perfectly fine
and u.lastname like '%fra%'
and c.CompanyRoleId in (2,3,4)

要么

select u.* 
from Users u inner join CompanyRolesToUsers c
             on u.Id = c.UserId    --explicit "join" statement, no diff from above, just preference
where u.lastname like '%fra%'
  and c.CompanyRoleId in (2,3,4)

话虽如此,在LINQ中它会是

from u in Users
from c in CompanyRolesToUsers 
where u.Id == c.UserId &&
      u.LastName.Contains("fra") &&
      selectedRoles.Contains(c.CompanyRoleId)
select u

要么

from u in Users
join c in CompanyRolesToUsers 
       on u.Id equals c.UserId
where u.LastName.Contains("fra") &&
      selectedRoles.Contains(c.CompanyRoleId)
select u

这也是表达这一点的可敬方式.在这两种情况下,我更喜欢显式的"连接"语法,但它有......


嗯,当你可以"加入和分离"时,为什么要"过滤".是因为"加入和分离"是自然而令人兴奋的SQL而"过滤器"只是不够令人兴奋吗?
好吧,既然我被邀请了......事实:没有优化器可以将Distinct(n ^ 2)变成过滤器(n).

3> Noah..:

这就是我在LINQ中做子查询的方式,我认为这应该得到你想要的.您可以将显式CompanyRoleId == 2 ...替换为您想要的不同角色的另一个子查询,也可以将其加入.

from u in Users
join c in (
    from crt in CompanyRolesToUsers
    where CompanyRoleId == 2
    || CompanyRoleId == 3
    || CompanyRoleId == 4) on u.UserId equals c.UserId
where u.lastname.Contains("fra")
select u;


他要求一个子查询!但我确信LINQ无论如何都将它改为同一个SQL ......
我必须在"== 4"之后加上"select crt"以避免错误"查询正文必须以select子句或group子句结束"
推荐阅读
爱唱歌的郭少文_
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有