2011-10-20 126 views
1

想象下列情況:LINQ與多個羣組加入

每個玩家(實體)都可以參與任意數量的攻擊(實體)。攻擊可能會導致殺戮(實體)。 Attack.Player映射到參與攻擊的玩家。殺死。攻擊導致殺死的攻擊地圖。因此,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?

非常感謝您的幫助!

+0

是否可以從播放器遍歷攻擊,然後從每個附加到殺死? – Ankur

+0

嗨,Ankur。感謝您的及時回覆。不,他們通過外鍵鏈接。所以,你有Attack.Player和Kill.Attack,但是你無法繞過它。 Wouter,謝謝, – Pato

回答

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

謝謝。這樣可行。也有很多可能的選擇。我試圖找到最乾淨,最簡潔的解決方案,並且允許將任意數量的表「加入」並將它們的列進行聚合 - 而無需進行額外的嵌套查詢。我在下面發佈的解決方案也是一個很好的解決方案。 – Pato

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) 
}