【问题标题】:C# linq group by on different keys in the same entityC# linq group by 在同一实体中的不同键上
【发布时间】:2012-06-10 15:52:56
【问题描述】:

我已经玩了一段时间了,就是搞不懂。我是 Linq、C# 和这些 Lambda 方面的新手。

我想做的是根据每个实体的两个属性对实体进行分组。这是一个消息实体:

Message
{
int UserId; //The user generating the message
int UserIdTo; //The receiver of the message
|...| // Other stuff 
}

所以,我希望这些 UserId=5, UserIdTo=6 和 UserId=6, UserIdTo=5 位于同一个组中。

这是我的开始:

var groupList = (from m in db.Messages
                             where m.UserId == userId || m.UserIdTo == userId
                             join u in db.Users on m.UserId equals u.UserId
                             join w in db.Users on m.UserIdTo equals w.UserId
                             orderby m.MessageTimestamp descending
                             select new DomMessage
                             {
                                 MessageId = m.MessageId,
                                 MessageContent = m.MessageContent,
                                 MessageTimestamp = m.MessageTimestamp,
                                 UserId = m.UserId,
                                 UserIdTo = m.UserIdTo,
                                 ScreenName = u.ScreenName,
                                 ScreenName2 = w.ScreenName
                             }).GroupBy(m=>m.UserId == userId)
                             .ToList();

这是按 UserId 进行分组的第一步,但我一直在尝试扩展它,以便结果组中的任何 UserId 值等于其他地方的 UserIdTo 将其添加到该组?

编辑:我需要将结果放到列表中,因为我还需要处理其他事情......

谢谢!

【问题讨论】:

    标签: c# asp.net linq lambda


    【解决方案1】:

    试试这个:

    var payload = new[] 
            {
                new{ To = 1, From = 2, Message = "msj1" },
                new{ To = 1, From = 2, Message = "msj2" },
                new{ To = 2, From = 1, Message = "msj3" },
                new{ To = 4, From = 1, Message = "msj4" },
                new{ To = 1, From = 3, Message = "msj5" }
            };
    
    
            var groupped = payload.Select(x => new { Key = Math.Min(x.To, x.From) + "_" + Math.Max(x.To, x.From), Envelope = x }).GroupBy(y => y.Key).ToList();
    
            foreach (var item in groupped)
            {
                Console.WriteLine(String.Format(@"Group: {0}, messages:", item.Key));
    
                foreach (var element in item)
                {
                    Console.WriteLine(String.Format(@"From: {0} To: {1} Message: {2}", element.Envelope.From, element.Envelope.To, element.Envelope.Message));
                }
            }
    

    【讨论】:

    • 感谢您的努力,但我遇到了同样的问题,例如,您的条目 new{ To = 1, From = 2, Message = "msj1" }new{ To = 2, From = 1, Message = "msj3" } 没有组合在一起
    • @testpattern 你有没有在控制台应用程序上尝试过这个?或者你的理论上。我可以将打印屏幕发送给您,让您了解它的工作原理。
    • 阿德里安,你说得对,它可以满足我的需要,谢谢!另外,对我来说在控制台应用上尝试一些东西是个好主意
    【解决方案2】:

    试试下面的 GroupBy 表达式:

    .GroupBy(m => Math.Min(m.UserId, m.UserIdTo) + ',' + Math.Max(m.UserId, m.UserIdTo))
    

    【讨论】:

    • 错误:(LINQ to Entities does not recognize the method 'Int32 Min(Int32, Int32)' method, and this method cannot be translated into a store expression.
    • 如果我有更多时间,我会尝试玩这个,因为它看起来很有希望......感谢您的努力!
    • 为了记录,这也是我需要的,通过添加尾随 ToList() 可以避免错误。我选择了 Adrian's,因为我需要他使用的信封。
    【解决方案3】:

    我认为这是最简单的方法:

    var groupList = from a in (
    from m in db.Messages
    where m.UserId == userId || m.UserIdTo == userId
    join u in db.Users on m.UserId equals u.UserId
    join w in db.Users on m.UserIdTo equals w.UserId
    select new 
    {
     MessageId = m.MessageId,
     MessageContent = m.MessageContent,
     MessageTimestamp = m.MessageTimestamp,
     UserId = m.UserId,
     UserIdTo = m.UserIdTo,
     ScreenName = u.ScreenName,
     ScreenName2 = w.ScreenName
    })
    group a by new { 
        UserId = a.UserId,
         UserIdTo = a.UserIdTo
        } into grp
    orderby grp.Max(a => a.MessageTimestamp) descending
    select new
    {
     UserId = grp.Key.UserId
     UserIdTo = grp.Key.UserIdTo,
     MessageId = grp.Max(a => a.MessageId),
     MessageContent = grp.Max(a => a.MessageContent),
     MessageTimestamp = grp.Max(a => a.MessageTimestamp),
     ScreenName = grp.Max(a => a.ScreenName),
     ScreenName2 = grp.Max(a => a.ScreenName2)
    }
    

    您必须告诉它如何处理您未分组的字段。在这种情况下,我得到了每个的 MAX 值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-01
      相关资源
      最近更新 更多