当id可以在第1列或第2列时进行分组

时间:2015-03-16 21:11:42

标签: c# sql entity-framework linq-to-sql

在我的网站上,会员可以互相发送消息。 这是我的Message类:

public partial class Message
{
    public System.Guid Id { get; set; }
    public System.DateTime DateMsg { get; set; }
    public string SenderId { get; set; }
    public string ReceiverId { get; set; }
    public string Text { get; set; }
}

我想做一个查询,获取每个已打开讨论的最后一条消息。由于我没有"讨论ID",我无法做到"按讨论ID"然后选择每个组中的第一个。 我该怎么办?

public IEnumerable<Message> Get_DiscussionsFor(string userId)
        {
            List<Message> list;
            using (var context = new ModelContainer())
            {
                IQueryable<Message> dbQuery = context.Set<Message>();               

                list = dbQuery
                    .AsNoTracking()
                    .Where(m => m.SenderId.Equals(userId) || m.ReceiverId.Equals(userId))
                    .OrderByDescending(m => m.DateMsg)                        
                    .ToList<Message>();
            }
            return list;
        }

1 个答案:

答案 0 :(得分:2)

嗯,这可能有用,虽然它不会很快。

以下是查询的第一部分:

            var list1 = dbQuery
                .AsNoTracking()
                .Where(m => m.SenderId.Equals(userId) || m.ReceiverId.Equals(userId));

我将创建另一个查询,它创建一个封装消息的匿名类型和另一个用户的ID。

            var senderFirst = list1
                .Where(m => m.SenderId.Equals(userId))
                .Select(
                 m => {
                   Message = m,
                   OtherUser = m.ReceiverId
                 });

我正在创建另一个,这次是我们想要的用户是接收者,而其他用户是发件人:

          var receiverFirst = list1
              .Where(m => m.ReceiverId.Equals(userId))
              .Select(
                m => {
                   Message = m,
                   OtherUser = m.SenderId,
                });

我现在正在联系他们。我可以这样做,因为它们具有相同类型和相同名称的完全相同的属性:在幕后,它们是相同的匿名类型。

            var list2 = senderFirst.Concat(receiverFirst);

因此,涉及您所需用户的每条消息都将与标识为OtherUser的其他用户一起显示。请注意,我们还没有更改Message对象:它仍然存在,SenderIdReceiverId的值正确。我们只是用另外的元数据将它包装在另一个对象中。

您说过涉及给定两个用户的任何消息都在同一个讨论中。因此,我们现在可以通过OtherUser

分组来讨论分组
             var list3 = list2.GroupBy(m => m.OtherUser);

所以现在我们已经分组了消息。您现在可以对每个组进行排序并选择最终消息。

             var list4 = list3
                 .Select(g => g.OrderByDescending(m => m.Message.DateMsg).First());

现在你拥有了List<Message>,因为你的Message对象仍在那里,准备从封装中脱颖而出:

             var list = list4
                 .Select(m => m.Message)
                 .ToList();