動的な「where」節をlinqクエリに追加するにはどうすればよいですか?
質問
ユーザーのロールを含むビットマスクを持つユーザーテーブルがあります。以下の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;
これを以下のメソッドに書き直して、指定されたロールからすべてのユーザーを返し、再利用できるようにします:
private List<User> GetUsersFromRoles(uint[] UserRoles) {}
クエリを動的に作成する方法に関するポインタはありますか?ありがとう
解決
PredicateBuilder クラスを使用できます。
PredicateBuilderは LINQKit NuGetパッケージでリリースされました
LINQKitは、LINQ to SQLおよびEntity Frameworkのパワーユーザー向けの拡張機能の無料セットです。
他のヒント
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);
}
おそらく、ループの代わりに機能する素晴らしいLINQ構文がありますが、概念は同じでなければなりません。
これを行うにはいくつかの方法があります:
LINQ動的クエリライブラリ: http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
式ツリー&amp;ラムダ式: http://msdn.microsoft.com/en-us/library/bb882637。 aspx
これは、LINQクエリに可変数の where 句を追加する1つの方法です。 ビットマスクロジックには触れていないことに注意してください。複数の where に注目しました。
// 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();
}
編集:実際には、これは AND where 句を使用し、それらを OR したいでしょう。次のアプローチ(内部結合)はLINQ to Objectsで機能しますが、LINQ to SQLを使用してSQLに変換することはできません。
var result = from user in Users
from role in UserRoles
where (user.UserRolesBitmask & role) == role
select user;
これはどうですか?動的な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;
}
private List<User> GetUsersFromRoles(uint UserRoles) {
return from u in dc.Users
where (u.UserRolesBitmask & UserRoles) != 0
select u;
}
UserRolesパラメーターは、配列ではなくビットマスクとして提供する必要があります。