根据 Entity Framework 中的值按某些列分组
Group by some columns depending on values in Entity Framework
我的 Entity Framework 代码中有以下简单语句:
query = query
.Where(c => c.NotificationType == NotificationType.AppMessage)
.GroupBy(c => c.ConversationId)
.Select(d => d.OrderByDescending(p => p.DateCreated).FirstOrDefault());
它只是根据带有 conversationId 和 select latest 的组来查找最新的 Notification
。简单。
然而,如果c.NotificationType == NotificationType.AppMessage
,这只是我想要的。如果该列不同于 AppMessage (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 语句。
我该如何解决这个问题?
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;
}
}
- 您根据 ConversationId 使用 "GroupBy" 过滤您的列表。接下来,根据结果创建一个字典并只制作一个列表 (SelectMany)。然后,您已经有了一个列表,其中应该只有您想要的具有 ConversationId 的记录。
最后一部分用于过滤此列表 - 您希望最后通知具有特定的 NotificationType。应该工作 :)
最简单的方法是在原始查询的末尾使用 Concat
编写 UNION ALL
查询:
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));
我的 Entity Framework 代码中有以下简单语句:
query = query
.Where(c => c.NotificationType == NotificationType.AppMessage)
.GroupBy(c => c.ConversationId)
.Select(d => d.OrderByDescending(p => p.DateCreated).FirstOrDefault());
它只是根据带有 conversationId 和 select latest 的组来查找最新的 Notification
。简单。
然而,如果c.NotificationType == NotificationType.AppMessage
,这只是我想要的。如果该列不同于 AppMessage (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 语句。
我该如何解决这个问题?
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;
}
}
- 您根据 ConversationId 使用 "GroupBy" 过滤您的列表。接下来,根据结果创建一个字典并只制作一个列表 (SelectMany)。然后,您已经有了一个列表,其中应该只有您想要的具有 ConversationId 的记录。
最后一部分用于过滤此列表 - 您希望最后通知具有特定的 NotificationType。应该工作 :)
最简单的方法是在原始查询的末尾使用 Concat
编写 UNION ALL
查询:
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));