Linq To Entities - как фильтровать дочерние объекты - PullRequest
13 голосов
/ 18 января 2011

У меня есть сущности Group и User.Group сущность имеет свойство Users, которое представляет собой список пользователей.У пользователя есть свойство с именем IsEnabled.

Я хочу написать запрос linq, который возвращает список Group с, который состоит только из User с чьим IsEnabled истинно.

так, например, для данных как нижеAllGroups Группа А Пользователь 1 (IsEnabled = true)Пользователь 2 (IsEnabled = true)Пользователь 3 (IsEnabled = false)

Группа B Пользователь 4 (IsEnabled = true)Пользователь 5 (IsEnabled = false)Пользователь 6 (IsEnabled = false)

хочу получитьFilteredGroups Группа А Пользователь 1 (IsEnabled = true)Пользователь 2 (IsEnabled = true)

Группа B Пользователь 4 (IsEnabled = true)

Я попробовал следующий запрос, но Visual Studio сообщает мне, что[Свойство или индексатор «Пользователи» не могут быть назначены - оно только для чтения]

FilteredGroups = AllGroups.Select(g => new Group()
                    {
                        ID = g.ID,
                        Name = g.Name,
                        ...
                        Users = g.Users.Where(u => u.IsInactive == false)
                    });

спасибо за помощь!

Ответы [ 5 ]

13 голосов
/ 18 января 2011

Нет «хорошего» способа сделать это, но вы можете попробовать это - спроецировать Group и отфильтрованный Users на анонимный объект, а затем Select только Groups:

var resultObjectList = AllGroups.
                       Select(g => new
                               {
                                   GroupItem = g,
                                   UserItems = g.Users.Where(u => !u.IsInactive)
                               }).ToList();

FilteredGroups = resultObjectList.Select(i => i.GroupItem).ToList();

Это не документированная функция, связанная с тем, как EF создает SQL-запросы - в этом случае она должна отфильтровывать дочернюю коллекцию, поэтому ваш список FilteredGroups будет содержать только активных пользователей.

Если это работает, вы можете попробовать объединить код:

FilteredGroups = AllGroups.
                 Select(g => new
                               {
                                   GroupItem = g,
                                   UserItems = g.Users.Where(u => !u.IsInactive)
                               }).
                 Select(r => r.GroupItem).
                 ToList();

(Это не проверено, и результат зависит от того, как EF обработает второй Select, поэтому было бы неплохо, если бы вы сообщили, какой метод работает после того, как вы его попробовали).

9 голосов
/ 13 мая 2011

Мне удалось сделать это, перевернув запрос вверх ногами:

var users = (from user in Users.Include("Group")
             where user.IsEnabled
             select user).ToList().AsQueryable()

from (user in users
      select user.Group).Distinct()

Используя ToList (), вы принудительно обращаетесь к базе данных в обе стороны, что необходимо, поскольку в противном случае на пути будет отложенное выполнение. Второй запрос только переупорядочивает полученные данные.

Примечание. После этого вы не сможете обновлять свои сущности!

1 голос
/ 13 мая 2011

попробуйте что-то вроде этого, и у вас все еще будут ваши сущности:

FilteredGroups = AllGroups.Select(g => new
{
    Group = g,
    Users = g.Users.Where(u => u.IsInactive == false)
}).AsEnumerable().Select(i => i.Group);

Таким образом, вы все равно сможете использовать Group.Users

0 голосов
/ 25 апреля 2019

Использовать внутренний запрос linq

var FilteredGroups = (from g in AllGroups
                      select new Group()
                        {
                            ID = g.ID,
                            Name = g.Name,
                            ...
                            Users = (from user in g.Users
                                     where user.IsInactive == false
                                     select user).ToList()
                        });
0 голосов
/ 16 мая 2013

Если вы хотите сохранить свою структуру сущностей, попробуйте следующее:

var userGroups = context.Users.Where(u => !u.IsInactive).GroupBy(u => u.Group);

foreach (var userGroup in userGroups)
{
    // Do group stuff, e.g.:
    foreach (var user in userGroup)
    {
    }
}

И вы, безусловно, можете изменить свои сущности!

...