В .NET Framework Entity Framework и Linq у меня возникла проблема поиска наилучшего (т.е. самого простого для чтения/понимания) способа реализации поиска того, содержит ли коллекция сущности любое из нескольких возможных значений.
Рассмотрим базовую реализацию членства/ролей, где Пользователь имеет коллекцию ролей.
Каким был бы "лучший" способ сказать: "имеет ли этот пользователь одну из следующих ролей: role1, role2 или role3?"
Я могу сделать это с 1 ролью, чтобы проверить, как в:
if myUser.Roles.Contains(role1) { // do something }
Есть ли простой способ добавить дополнительные роли в эту проверку?
EDIT: Я только что провел несколько тестов. Интересно, что перфомант довольно идентичен для IN против OR, поэтому, кроме SQL, выглядя уродливым, они выполняют почти то же самое. Я отредактировал свой ответ, чтобы отразить это.
Запросы в стиле "IN" не являются неотъемлемой поддержкой EF (пока) Я считаю, что то, что вы пытаетесь выполнить, было рассмотрено here
Вы можете получить соответствующие объекты с чем-то вроде этого:
var roleNamesToMatch = {"Admin","Manager","Associate"};
var expression = BuildOrExpression<Role, name>(r => r.Name, roleNamesToMatch);
var matchingRoles = context.RoleSet.Where(expression);
На основе дерева выражений EF создаст SQL, который выглядит примерно так:
select r.ID,r.Name from t_Role where r.Name = 'Admin' OR r.Name = 'Manager'
OR r.Name = 'Associate'
вместо того, что обычно ожидалось
select r.ID,r.Name from t_Role where r.Name in ('Admin','Manager','Associate')
Если список ролей известен во время компиляции, вы можете сделать что-то вроде этого:
if (myUser.Roles.Count(r => r.Id == role1.Id || r.Id == role2.Id) > 0)
{
// do something
}
Если вы хотите проверить динамический список ролей, это становится сложнее. Сообщите мне, если это то, что вам нужно.
EDITED изменен Any()
на Count() > 0
- я неправильно понял это ограничение в L2E и L2SQL.
Использование Count()
сделает больше работы, чем необходимо. Вы можете комбинировать проверки идентификаторов ролей с методом Any()
для проверки наличия:
if(myUser.Roles.Any(role => role.Id == role1.Id || role.Id == role2.Id)
{
// ...
}
var checkForRoles = new Role[] { Role1, Role2, Role3 };
if (myUser.Roles.Any(r => search.Contains(checkForRoles))) {
//the user is in one of the roles.
}