C# 如何向 linq 查询添加动态“where”子句?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/180405/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 16:51:37  来源:igfitidea点击:

How do you add dynamic 'where' clauses to a linq query?

c#linqdynamic

提问by Nick

I've got a User table with a bitmask that contains the user's roles. The linq query below returns all the users whose roles include 1, 4 or 16.

我有一个带有位掩码的 User 表,其中包含用户的角色。下面的 linq 查询返回角色包括 1、4 或 16 的所有用户。

var users = from u in dc.Users
            where ((u.UserRolesBitmask & 1) == 1)
               || ((u.UserRolesBitmask & 4) == 4)
               || ((u.UserRolesBitmask & 16) == 16)
            select u;

I'd like to rewrite this into the method below to returns all the users from the given roles so I can reuse it:

我想将其重写为下面的方法,以返回给定角色的所有用户,以便我可以重用它:

private List<User> GetUsersFromRoles(uint[] UserRoles) {}

Any pointers on how to dynamically build my query? Thanks

关于如何动态构建我的查询的任何指示?谢谢

采纳答案by ilitirit

You can use the PredicateBuilderclass.

您可以使用PredicateBuilder类。

PredicateBuilder has been released in the LINQKit NuGet package

PredicateBuilder 已在LINQKit NuGet 包中发布

LINQKit is a free set of extensions for LINQ to SQL and Entity Framework power users.

LINQKit 是 LINQ to SQL 和实体框架高级用户的免费扩展集。

回答by Dylan Beattie

Assuming your UserRoles values are themselves bitmasks, would something like this work?

假设您的 UserRoles 值本身就是位掩码,这样的操作会起作用吗?

private List<User> GetUsersFromRoles(uint[] UserRoles) {
    uint roleMask = 0;
    for (var i = 0; i < UserRoles.Length;i++) roleMask= roleMask| UserRoles[i];
    // roleMasknow contains the OR'ed bitfields of the roles we're looking for

    return (from u in dc.Users where (u.UserRolesBitmask & roleMask) > 0) select u);
}

There's probably a nice LINQ syntax that'll work in place of the loops, but the concept should be the same.

可能有一个很好的 LINQ 语法可以代替循环,但概念应该是相同的。

回答by Carlton Jenke

How's this? It is not dynamic linq, but accomplishes the goal.

这个怎么样?它不是动态 linq,而是实现了目标。

private List<User> GetUsersFromRoles(uint[] userRoles) 
{
    List<User> users = new List<User>();

    foreach(uint userRole in UserRoles)
    {
        List<User> usersInRole = GetUsersFromRole(userRole);
        foreach(User user in usersInRole )
        {
            users.Add(user);
        }
    }
    return users;
}    

private List<User> GetUsersFromRole(uint userRole) 
{
    var users = from u in dc.Users
            where ((u.UserRolesBitmask & UserRole) == UserRole)
            select u;

    return users;    
}

回答by alexmac

回答by Michael Damatov

private List<User> GetUsersFromRoles(uint UserRoles) {
  return from u in dc.Users            
         where (u.UserRolesBitmask & UserRoles) != 0
         select u;
}

UserRoles parameter should be provided, however, as a bit mask, instead of array.

但是,应提供 UserRoles 参数作为位掩码,而不是数组。

回答by Lucas

Here's one way of adding a variable number of whereclauses to your LINQ query. Note that I haven't touched your bitmask logic, I just focused on the multiple wheres.

这是向 LINQ 查询添加可变数量的where子句的一种方法。请注意,我没有触及您的位掩码逻辑,我只是​​关注了多个wheres。

// C#
private List<User> GetUsersFromRoles(uint[] UserRoles)
{
   var users = dc.Users;

   foreach (uint role in UserRoles)
   {
      users = users.Where(u => (u.UserRolesBitmask & role) == role);
   }

   return users.ToList();
}


EDIT: Actually, this will ANDthe whereclauses and you wanted to ORthem. The following approach (a inner join) works in LINQ to Objects but can not be translated to SQL with LINQ to SQL:

编辑:其实,这种意志那里条款和你想他们。以下方法(内部联接)适用于 LINQ to Objects,但无法使用 LINQ to SQL 转换为 SQL:

var result = from user in Users
             from role in UserRoles
             where (user.UserRolesBitmask & role) == role
             select user;