2012-06-06 3 views
4

Я некоторое время играл с этим и просто не могу его получить. Я новичок в Linq, C# и этих предметах Lambda.C# linq group по разным клавишам в одном объекте

Что я хочу сделать, это группировать объекты в соответствии с двумя свойствами для каждого объекта. Это предприятие сообщение:

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 где-то еще добавить к этой группе?

EDIT: Мне нужен результат, чтобы пойти в список, потому что есть другие вещи, мне нужно с ним делать ...

Спасибо!

ответ

2

Попробуйте это:

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)); 
      } 
     } 
+0

спасибо за это, но я получаю ту же проблему, где, например, ваши записи 'new {To = 1, From = 2 , Message = "msj1"} 'и' new {To = 2, From = 1, Message = "msj3"} 'не сгруппированы вместе – testpattern

+1

@testpattern Вы когда-нибудь пробовали это на ac onsole App? Или теоретически. Я могу отправить вам экран печати, чтобы показать, что он работает. –

+0

Адриан, ты прав, он делает то, что мне нужно, спасибо! Также, хорошая идея для меня попробовать вещи на консольном приложении. – testpattern

1

Попробуйте следующее выражение GroupBy:

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

Концептуально хорошо, но мне интересно, если ОРМ сможет перевести его ... – AakashM

+0

Ошибка :( 'LINQ к Entities не распознает метод«Int32 Мин (Int32, Int32)»метод, и этот метод не может быть переведено в выражение в магазине. « – testpattern

+0

Если я получу еще немного времени, я попробую сыграть с этим, поскольку он выглядит многообещающим ... спасибо за это! – testpattern

0

Я думаю, что это самый простой способ:

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 для каждого.

Смежные вопросы