2011-05-14 6 views
7

Bu Sql ifadesine sahibimÖnce bu SQL'i EF 4 Kodu için lambdaya dönüştürün

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 

Bu lambda ifadesine dönüştürmek istiyorum.

Bu şekilde çalışıyor.

Bir oyun sadece 1 seriye katılabilir, ancak bir seri elbette birçok oyuna sahip olabilir. Bir seride birçok takım olabilir ve bir takım birçok seriye katılabilir. Bir takım birçok takımda oynayabilir ve bir takımın birçok oyuncusu vardır.

SeriesTeams ve TeamPlayers, EF tarafından seri/takımlar ile Takımlar/Oyuncular

arasındaki referansları saklı tutmak için hazırladığımız çoktan çoğa çoklu çizelgelerdir. Şimdiden teşekkürler ...

Edit: kullanıyorum EF 4 CTP5 ve cevabı lambda işlevi olarak kullanmak ister, ya da daha kolaysa linq ...

cevap

3

Tamam, her şeyden önce, şunları yapmalısınız açık Include ekleyin: benim açıklamada belirtildiği gibi çocuk koleksiyonundan oyuncu filtre olmadığı için

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(); 

Ancak, bu, SQL sorgusu ile aynı sonuç vermez.

EF 4.1, bazı şık Applying filters when explicitly loading related entities özelliklerine sahiptir, ancak alt alt koleksiyonlar için çalışmaya yetişemedim, bu yüzden orijinal sorgunuza ulaşabileceğiniz en yakın nokta, sonuçları anonim bir nesneye yansıtmak olacaktır. (Daha sonra etrafında bu nesneyi geçmesi gerekiyorsa ya da bunun için bir sınıf oluşturabilirsiniz):

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

sonra numaralandırmak ve sonuçlarını inceleyebilirsiniz:

var gamesAndPlayersList = query.ToList(); 
+0

Merhaba. Denerim. EF tarafından üretilen SQL deyimi, orjinal sql deyimim kadar "güzel" değil. Bir yolu, tam olarak farklı tablolardan istediğim bilgiyi veren bir Görünüm oluşturmak ve bunun yerine bunu yürütmek ve sonra bu özel varlığı bu sonuçla eşleştirmek için oluşturmak olabilir. Yukarıdakileri yapmak kadar güzel olmaz, ama veri tabanına karşı daha iyi bir performans verebilirim. Fazladan çalışmaya değecek bir performans testi yapmak zorundayım. –

1

Çözümü buldum. Biri daha sonra daha iyi bir çözüm varsa

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(); 

dinliyorum ben size, her şeyi istekli yüklü Eğer sorgu çalıştırdığınızda olduğundan emin olmak istiyorsanız ..

+0

Bu aynı vermeyecektir olsa da, SQL sorgunuz olarak sonuçlanır. Aradaki fark, SQL sorgusunun sadece 'Id == 1' olan oyuncuları döndürürken, LINQ sorgunuz player 1 için oyunların bir listesini döndürecek, fakat aynı takımdaki oyuncularla birlikte TÜM oyuncularla (1) filtrelenmedi). Bu aslında aradığınız çıktı mı? Ayrıca, tembel yükleme olmadan, herhangi bir navigasyon özelliğine bile erişemezsiniz (sadece “Oyunlar” DB'den yüklenecektir). EF'in hangi sürümünü kullanıyorsunuz? – Yakimych

+0

Evet, EF4 CTP5 olduğunu görüyorum - üzgünüm, sorunuzu yeniden okumadım ve yorumumu göndermeden önce düzenlemeyi görmedim. EF4.1'e geçmemek için herhangi bir sebep var mı? – Yakimych

+0

Üzgünüm! EF4.1 kullanıyorum EF4 CTP5 eski habbit olmalı :). Takımdaki tüm oyuncuları oyuncu olarak ele aldığımı düşünürsek 1. Sadece oyuncu 1 için oyunları göstermek için lambda ifadesini nasıl değiştirmeliyim? –