2011-05-14 4 views
7

J'ai cette déclaration SqlConvertir ce SQL lambda pour EF 4 Code premier

SELECT * FROM Game 
     INNER JOIN Series ON Series.Id = Game.SeriesId 
     INNER JOIN SeriesTeams ON SeriesTeams.SeriesId = Series.Id 
     INNER JOIN Team ON Team.Id = SeriesTeams.TeamId 
     INNER JOIN TeamPlayers ON TeamPlayers.TeamId = Team.Id 
     INNER JOIN Player ON Player.Id = TeamPlayers.PlayerId 
    WHERE AND Game.StartTime >= GETDATE() 
     AND Player.Id = 1 

que je veux être converti en une expression lambda.

Voici comment cela fonctionne.

Un jeu ne peut être joint qu'à une série, mais une série peut bien sûr avoir beaucoup de jeux. Une série peut avoir plusieurs équipes et une équipe peut rejoindre plusieurs séries. Un joueur peut jouer dans plusieurs équipes et une équipe a beaucoup de joueurs.

SeriesTeams et TeamPlayers ne sont que le nombre à plusieurs tables créées par EF pour tenir les références entre les séries/équipes et équipes/joueurs

Merci à l'avance ...

Edit: J'utilise le EF 4 CTP5 et voudrait avoir la réponse en tant que fonctions lambda, ou en linq si c'est plus facile ...

Répondre

3

Ok, tout d'abord, si vous voulez vous assurer que tout est impatient chargé lorsque vous exécutez votre requête, vous devriez ajouter un Include explicite:

context. 
Games. 
Include(g => g.Series.Teams.Select(t => t.Players)). 
Where(g => 
     g.StartTime >= DateTime.Now && 
     g.Series.Teams.Any(t => t.Players.Any(p => p.Id == 1))). 
ToList(); 

Cependant, comme je l'ai mentionné dans mon commentaire, cela ne produira pas les mêmes résultats que votre requête SQL, puisque vous ne filtrent pas les joueurs de la collection des enfants. EF 4.1 a quelques astucieuses fonctionnalités Applying filters when explicitly loading related entities, mais je ne pouvais pas l'utiliser pour les sous-sous-collections, donc je pense que le plus proche de votre requête originale serait de projeter les résultats sur un objet anonyme (ou vous pouvez créer une classe pour que si vous devez passer cet objet autour de la suite):

var query = context. 
      Games. 
      Where(g => 
        g.StartTime >= DateTime.Now && 
        g.Series.Teams.Any(t => t.Players.Any(p => p.Id == 1))). 
      Select(g => new 
         { 
          Game = g, 
          Players = g. 
             Series. 
             Teams. 
             SelectMany(t => t. 
                 Players. 
                 Where(p => p.Id == user.Id)) 
         }); 

Ensuite, vous pouvez énumérer et inspecter les résultats:

var gamesAndPlayersList = query.ToList(); 
+0

Bonjour. Je vais l'essayer. Je suppose que l'instruction SQL produite par EF n'est pas aussi "belle" que mon instruction sql originale. Une façon pourrait être de créer une vue qui me donne exactement l'information que je veux à partir des différentes tables, et de l'exécuter à la place, puis de créer cette entité spéciale pour correspondre à ce résultat. Ne serait pas aussi bien que de faire ce qui précède, mais pourrait me donner de meilleures performances contre la base de données. Je dois faire un test de performance pour décider si ça vaut le travail supplémentaire. –

1

J'ai trouvé la solution.

IList<Domain.Model.Games> commingGames = this.Games 
.Where(a => a.StartTime >= DateTime.Now && a.Series.Teams.Any(t => t.Players.Any(p => p.Id == user.Id))).ToList(); 

Si quelqu'un a une meilleure solution alors je suis toutes les oreilles ..

+0

cela ne donnera pas le même résultats en tant que votre requête SQL, cependant. La différence est que la requête SQL renvoie uniquement les joueurs avec 'Id == 1', alors que votre requête LINQ retournera une liste de jeux pour le joueur 1, mais avec TOUS les joueurs de la même équipe que le joueur 1 (la collection enfant est pas filtré). Est-ce la sortie que vous recherchez? De plus, sans chargement par la poste, vous ne pourrez même pas accéder aux propriétés de navigation (seuls les «jeux» seront chargés depuis la base de données). Quelle version de EF utilisez-vous? – Yakimych

+0

Oui, je vois que c'est EF4 CTP5 - désolé je n'ai pas relu votre question et voir la modification avant de poster mon commentaire. Une raison pour ne pas passer à EF4.1, btw? – Yakimych

+0

Désolé! J'utilise en fait EF4.1 le EF4 CTP5 doit être de vieux habbit :). En ce qui concerne cela, je reçois tous les joueurs de l'équipe en tant que joueur 1. Comment devrais-je changer l'expression lambda pour montrer uniquement les jeux pour le joueur 1? –

Questions connexes