Ответ 1
Вы можете использовать класс PredicateBuilder.
PredicateBuilder был выпущен в пакет LINQKit NuGet
LINQKit - это бесплатный набор расширений для пользователей с поддержкой LINQ to SQL и Entity Framework.
У меня есть таблица 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;
Я хотел бы переписать это в приведенный ниже метод, чтобы вернуть всех пользователей из заданных ролей, чтобы я мог его повторно использовать:
private List<User> GetUsersFromRoles(uint[] UserRoles) {}
Любые указатели на то, как динамически строить мой запрос? Благодаря
Вы можете использовать класс PredicateBuilder.
PredicateBuilder был выпущен в пакет LINQKit NuGet
LINQKit - это бесплатный набор расширений для пользователей с поддержкой LINQ to SQL и Entity Framework.
Есть несколько способов сделать это:
LINQ Динамические библиотеки запросов: http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
Деревья выражений и выражения Lamda: http://msdn.microsoft.com/en-us/library/bb882637.aspx
Здесь один из способов добавить переменное число предложений where к вашему запросу LINQ. Обратите внимание, что я не коснулся логики битмаски, я просто сосредоточился на нескольких типах.
// 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: на самом деле это будет И предложения where, и вы хотели бы ИЛИ их. Следующий подход (внутреннее соединение) работает в LINQ для объектов, но не может быть переведен на SQL с LINQ to SQL:
var result = from u in Users
from role in UserRoles
where (u.UserRolesBitmask & role) == role)
select u;
Предполагая, что ваши значения 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, но выполняет цель.
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 должен быть предоставлен, однако, как битовая маска вместо массива.