Как я могу определить, содержит ли коллекция сущностей одно из нескольких возможных значений?

2

В .NET Framework Entity Framework и Linq у меня возникла проблема поиска наилучшего (т.е. самого простого для чтения/понимания) способа реализации поиска того, содержит ли коллекция сущности любое из нескольких возможных значений.

Рассмотрим базовую реализацию членства/ролей, где Пользователь имеет коллекцию ролей.

Каким был бы "лучший" способ сказать: "имеет ли этот пользователь одну из следующих ролей: role1, role2 или role3?"

Я могу сделать это с 1 ролью, чтобы проверить, как в:

if myUser.Roles.Contains(role1) { // do something }

Есть ли простой способ добавить дополнительные роли в эту проверку?

Теги:
linq
entity-framework

4 ответа

2

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')
  • 0
    Нет никакой разницы в производительности SQL между IN (...) и рядом операторов OR. С точки зрения планирования запросов они одинаковы.
  • 0
    Да, ты прав ... Я отредактировал свой ответ, чтобы отразить это.
2

Если список ролей известен во время компиляции, вы можете сделать что-то вроде этого:

if (myUser.Roles.Count(r => r.Id == role1.Id || r.Id == role2.Id) > 0)
{ 
    // do something 
}

Если вы хотите проверить динамический список ролей, это становится сложнее. Сообщите мне, если это то, что вам нужно.

EDITED изменен Any() на Count() > 0 - я неправильно понял это ограничение в L2E и L2SQL.

  • 0
    .Any () не подходит для Linq to Entities .... но это похоже на то, чего я хочу достичь ....
1

Использование Count() сделает больше работы, чем необходимо. Вы можете комбинировать проверки идентификаторов ролей с методом Any() для проверки наличия:

if(myUser.Roles.Any(role => role.Id == role1.Id || role.Id == role2.Id)
{
    // ...
}
0
var checkForRoles = new Role[] { Role1, Role2, Role3 };

if (myUser.Roles.Any(r => search.Contains(checkForRoles))) {
   //the user is in one of the roles. 
}
  • 1
    Структура сущностей не поддерживает Contains (), и, во всяком случае, Contains () не принимает массив или IEnumerable в качестве параметра - поэтому я не уверен, что это должно делать.
  • 0
    Ты прав. Я не знал, что EF не поддерживает Contains. Я искал способ получить динамический список для проверки. Сегодня утром я проводил некоторые тесты, кажется, что EF тоже не работает с Intersect - меня испортил L2S.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню