Группировать по нескольким столбцам в зависимости от значений в 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;
}
}
- Вы фильтруете свой список с помощью "GroupBy" на основе ConversationId. Далее создайте словарь из результата и составьте только один список (SelectMany). Тогда у вас уже есть один список, в котором должны быть только записи с ConversationId, который вы хотите.
Последняя часть предназначена для фильтрации этого списка - вы хотели получить последнее уведомление с определенным NotificationType. Должно работать:)