Есть ли эквивалентное утверждение в EF для выражения LINQ? - PullRequest
0 голосов
/ 26 февраля 2020

У меня есть метод, который позволяет получать участников, которые не заблокированы и не являются самостоятельными, из указанной c комнаты чата. Есть ли способ поместить все операторы в один оператор БД, более элегантное компактное решение.

  Task<IList<ChatParticipant>> GetParticipants(int chatId, int excludeUserId)
        { 

            var chatParticipants = await Context.ChatParticipant
                .Include(x => x.Chat)
                .Include(x => x.Participant)
                .Where(c => c.ParticipantId != excludeUserId)
                .ToListAsync();

            var blockers = await Context.BlockedParticipant 
                .Include(x => x.Blocker)
                .Where(c => c.BlockedId == excludeUserId)
                .Select(x => x.Blocker)
                .ToListAsync();


            var result = chatParticipants.Where(p => blockers.All(p2 => p2.Id != p.ParticipantId)).ToList();

            return result;
        }

Ответы [ 2 ]

1 голос
/ 26 февраля 2020

Хотя я согласен с тем, что разделение запросов улучшает читабельность, другое соображение заключается в том, что два запроса будут загружать все соответствующих данных в память перед фильтрацией и разбиением на страницы и т. Д. c. Это будет дорого на ресурсах сервера. Получив удар по отношениям, вы можете попробовать что-то вроде:

Task<IList<ChatParticipant>> GetParticipants(int chatId, int excludeUserId)
{ 

    var chatParticipants = await Context.ChatParticipant
        .Include(x => x.Chat)
        .Include(x => x.Participant)
        .Where(c => c.ParticipantId != excludeUserId
            && !Context.BlockedParticipant.Any(b => 
                 b.BlockedId == excludeUserId && b.Blocker.Id == c.ParticipantId))
        .ToListAsync();

    return chatPaticipants;
}

Я считаю, что метод также должен быть помечен как async, чтобы упростить await и избежать потенциального многопоточного доступа в DbContext. , Я не уверен на 100%, что уловил отношения между блокировщиком и участником, но это было то, что я мог вывести из исходных запросов. Объединение их в один запрос не способствует удобочитаемости, но позволяет избежать загрузки больших наборов в память перед чем-то вроде разбивки на страницы.

1 голос
/ 26 февраля 2020

Я бы предложил преобразовать !All в пустое объединение в группу. Я не проверял это с EF, однако:

var chatParticipants = Context.ChatParticipant
               .Include(x => x.Chat)
               .Include(x => x.Participant)
               .Where(c => c.ParticipantId != excludeUserId);

var blockers = Context.BlockedParticipant
    .Include(x => x.Blocker)
    .Where(c => c.BlockedId == excludeUserId)
    .Select(x => x.Blocker);


var ans = from cp in chatParticipants
          join bp in blockers on cp.ParticipantId equals bp.Id into bpj
          where !bpj.Any()
          select cp;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...