Фильтровать строки перед .ToList (), используя LINQ и Entity Framework - PullRequest
2 голосов
/ 08 марта 2020

У меня есть несколько таблиц:

NotificationQueue

NotQueueId OrderId CreateDateTime      SentDateTime NotType
1          Order1  2020-02-25 10:37:17 NULL         Failure
2          Order1  2020-02-25 16:37:18 NULL         Escalation
3          Order2  2020-02-24 04:37:16 NULL         Failure
4          Order2  2020-02-24 10:37:17 NULL         Escalation
5          Order3  2020-02-26 10:30:17 NULL         Failure
6          Order4  2020-02-26 10:10:17 NULL         Failure
7          Order4  2020-02-26 16:10:18 NULL         Escalation
8          Order5  2020-02-26 10:10:17 NULL         Failure

FailedTickets

FailedTicketId OrderId StatusId FailedReason     CreateDateTime      UpdateDateTime
1              Order1  2        Somereason1      2020-02-25 10:37:17 NULL
2              Order2  3        Somereason2      2020-02-24 04:37:16 NULL
2              Order3  3        Somereason3      2020-02-26 10:30:17 NULL
2              Order4  5        Cancelled        2020-02-26 10:10:17 2020-02-27 16:10:18
2              Order5  4        Succeeded Later  2020-02-26 10:10:17 2020-02-25 01:37:16

Статус

StatusId StatusDESC
1        Initial
2        Validated
3        Saved
4        Complete
5        Cancelled

По сути, здесь происходит следующее:

  1. Каждый раз, когда происходит сбой какого-либо билета, он помещается в таблицу FailedTickets и также толкается на NotificationQueue и остается там, чтобы некоторые электронная почта подобрала ее, отправила электронное письмо и обновила столбец SendDateTime .
  2. После того, как билет не разрешен в течение 6 часов, новая строка помещается в таблицу NotificationQueue , указывающую, что билет должен быть увеличен.

Требуемый вывод is:

  1. Не возвращать билеты, которые отменены или завершены .
  2. Если тот же Идентификатор заказа перешел на Повышение , пропустите строку, созданную для Ошибка в целом и только вернуть строку Escalation .
  3. Вернуть все билеты, которые не прошли (если они еще не обострились).

Пример вывода с использованием таблиц и критериев, упомянутых выше :

NotType    OrderId Status    FailedReason CreateDateTime      NotQueueId SentDateTime
Escalation Order1  Validated Somereason1  2020-02-25 16:37:18 2          NULL
Escalation Order2  Saved     Somereason2  2020-02-24 10:37:17 4          NULL
Failure    Order3  Saved     Somereason3  2020-02-26 10:30:17 5          NULL

НО в настоящее время я могу только получить это:

NotType    OrderId Status    FailedReason CreateDateTime      NotQueueId SentDateTime
Failure    Order1  Validated Somereason1  2020-02-25 10:37:17 1          NULL
Escalation Order1  Validated Somereason1  2020-02-25 16:37:18 2          NULL
Failure    Order2  Saved     Somereason2  2020-02-24 04:37:16 3          NULL
Escalation Order2  Saved     Somereason2  2020-02-24 10:37:17 4          NULL
Failure    Order3  Saved     Somereason3  2020-02-26 10:30:17 5          NULL

с этим кодом:

var skippableStatuses = new List<string> { "Complete", "Cancelled" };
var failedAndEscalatedRows = (from nq in somedbContext.NotificationQueues
               join ft in somedbContext.FailedTickets on nq.OrderID equals ft.OrderID
               join s in somedbContext.Statuses on ft.StatusID equals os.StatusID
               select new
               {
                   CreatedDate = nq.CreateDatetime,
                   NotificationType = nq.NotType,
                   NotQueueId = nq.NotQueueId,
                   OrderId = nq.OrderId,
                   SentTime = nq.SentDateTime,
                   Reason = ft.FailedReason,
                   Status = s.StatusDESC
               }
           ).Where(e => !skippableStatuses.Contains(e.Status)).ToList();

Теперь я, вероятно, могу oop через эти записи и найдите те, которые имеют Эскалация статус. Но я не хочу возвращать строки, которые мне даже не нужны, поэтому перед вызовом .ToList () я хочу создать запрос LINQ, который будет возвращать только требуемые строки и вообще избегать циклов.

Я уверен, что должен быть лучший способ сделать это, поэтому я обратился к ТАК!

1 Ответ

0 голосов
/ 08 марта 2020

Что вам нужно, это сделать некоторую фильтрацию и сгруппировать данные вашей первой таблицы (NotificationQueues) перед выполнением какого-либо соединения, что-то вроде этого:

 var failedAndEscalatedRows = 

    (from nq in somedbContext.NotificationQueues.GroupBy(c => c.OrderId).Select(c => new
    {
         c.Key,
         CreateDatetime = c.Select(d => d.CreateDateTime).FirstOrDefault(),
         NotQueueId = c.Select(d => d.NotQueueId).FirstOrDefault(),
         NotType = c.Count() > 1 ? c.FirstOrDefault(d => d.NotType == "Escalation").NotType 
             : c.FirstOrDefault(d => d.NotType == "Failure").NotType,
         SentDateTime = c.Select(d => d.SentDateTime).FirstOrDefault()
    })

        join ft in somedbContext.FailedTickets on nq.Key equals ft.OrderId
        join s in somedbContext.Statuses on ft.StatusId equals s.StatusId
        select new
        {
            CreatedDate = nq.CreateDatetime,
            NotificationType = nq.NotType,
            NotQueueId = nq.NotQueueId,
            OrderId = nq.Key,
            SentTime = nq.SentDateTime,
            Reason = ft.FailedReason,
            Status = s.StatusDESC
        }
    ).Where(e => !skippableStatuses.Contains(e.Status)).ToList();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...