具有多个GroupJoin的LINQ

时间:2011-10-20 06:46:20

标签: c# linq

想象一下以下情况:

每个玩家(一个实体)可以参与任意数量的攻击(一个实体)。攻击可能导致杀死(实体)。 Attack.Player映射到攻击中涉及的玩家。 Kill.Attack映射到导致杀戮的攻击。因此,Kill.Attack.Player会将杀戮映射到玩家。

我想制作以下报告: 玩家A造成10次攻击,造成7次杀戮。 玩家B造成8次攻击,造成4次死亡。 玩家C进行了0次攻击,导致0次杀伤。

如何使用LINQ进行此操作?我以为我能做到:

from player in Players
join attack in Attacks on player equals attack.Player into attacksByPlayer
join kill in Kills on attack equals kill.Attack into killsByPlayer
select new { Player = player, Attacks = attacksByPlayer.Count(), Kills = killsByPlayer.Count() }

显然,由于各种原因(并且不会构建),这是不正确的。

另外,我如何创建相同的报告,但是使用内部联接,因为他没有攻击而不会报告玩家C?

非常感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

以下查询应该可以解决问题。它只会显示发起攻击的玩家,并会为你计算攻击和杀戮。

using (Model m = new Model())
{
    var result = from attack in m.Attacks
                 group attack by attack.Player into attacksForPlayer
                 select new
                 {
                     PlayerName = attacksForPlayer.Key.Name,
                     NumberOfAttacks = attacksForPlayer.Count(),
                     NumberOfKills = (from k in m.Kills
                                      where attacksForPlayer.Contains(k.Attack)
                                      select k).Count()
                 };

    // The result can be read like this:
    foreach (var r in result)
    {
        // r.PlayerName, r.NumberOfAttacks, r.NumberOfKills
    }
}

答案 1 :(得分:1)

from player in players
from attack in attacks.Where(attack => attack.Player == player).DefaultIfEmpty()
from kill in kills.Where(kill => kill.Attack == attack).DefaultIfEmpty()
group new { attack, kill } by player into g
select new {
    Player = player, 
    Attacks = g.Count(x => x.attack != null),
    Kills = g.Count(x => x.kill != null)
}