Группировать по нескольким столбцам в зависимости от значений в Entity Framework

В моем коде Entity Framework есть следующее простое утверждение:

        query = query
                .Where(c => c.NotificationType == NotificationType.AppMessage)
                .GroupBy(c => c.ConversationId)
                .Select(d => d.OrderByDescending(p => p.DateCreated).FirstOrDefault());

Он просто находит последние Notification на основе группы с разговорным идентификатором и выберите последний. Легко.

Тем не менее, это только то, что я хочу, если c.NotificationType == NotificationType.AppMessage, Если столбец отличается от AppMessa ge (c.NotificationType <> NotificationType.AppMessageЯ просто хочу столбец. То, что я действительно хочу написать, является волшебным утверждением, таким как:

         query = query
                .Where(c => (c.NotificationType <> NotificationType.AppMessage) 
                || ((c.NotificationType == NotificationType.AppMessage)
                .GroupBy(c => c.ConversationId)
                .Select(d => d.OrderByDescending(p => p.DateCreated).FirstOrDefault()));

Но это не имеет смысла, потому что GroupBy/Select основан на первом операторе where.

Как мне это решить?

2 ответа

Решение

Самый простой способ - составить UNION ALL запрос с использованием Concat в конце вашего исходного запроса:

query = query
    .Where(c => c.NotificationType == NotificationType.AppMessage)
    .GroupBy(c => c.ConversationId)
    .Select(d => d.OrderByDescending(p => p.DateCreated).FirstOrDefault())
    .Concat(query.Where(c => c.NotificationType != NotificationType.AppMessage));
public class EntityClass
{
    public int NotificationType { get; set; }

    public int ConversationId { get; set; }

    public DateTime Created { get; set; }

    public static EntityClass GetLastNotification(int convId)
    {
        var list = new List<EntityClass>(); // Fill the values

        list = list
            .GroupBy(i => i.ConversationId) // Group by ConversationId.
            .ToDictionary(i => i.Key, n => n.ToList()) // Create dictionary.
            .Where(i => i.Key == convId) // Filter by ConversationId.
            .SelectMany(i => i.Value) // Project multiple lists to ONLY one list.
            .ToList(); // Create list.

        // Now, you can filter it:

        // 0 - NotificationType.AppMessage
        // I didn't get what exactly you want to filter there, but this should give you an idea.
        var lastNotification = list.OrderByDescending(i => i.Created).FirstOrDefault(i => i.NotificationType == 0);
        return lastNotification;
    }
}
  1. Вы фильтруете свой список с помощью "GroupBy" на основе ConversationId. Далее создайте словарь из результата и составьте только один список (SelectMany). Тогда у вас уже есть один список, в котором должны быть только записи с ConversationId, который вы хотите.

Последняя часть предназначена для фильтрации этого списка - вы хотели получить последнее уведомление с определенным NotificationType. Должно работать:)

Другие вопросы по тегам