2011-08-23 15 views
11

Rozważmy:LINQ podmiotom + Dołącz typu + Anonymous problem

klasy Client

Klasa projektu

Class Ticket

Class Odpowiedz

Klienci mają kolekcję sub projektów, projekty mają pod kolekcję biletów i biletów mają pod kolekcję odpowiedzi.

var data = ctx.Set<Ticket>().Include(p => p.Client). 
Select(p => new { Ticket = p, LastReplyDate = p.Replies.Max(q => q.DateCreated)}); 

Nie działa. Ani projekt, ani klient nie są ładowani podczas wybierania danych w ten sposób.

Wiem, jak to działa. Moje pytanie brzmi: dlaczego tak nie działa?

Odpowiedz

10

Jak wspomniał Ladislav, Include działa tylko wtedy, gdy bezpośrednio wybierzesz jednostkę Ticket. Ponieważ wyświetlasz inne informacje, Include zostaje zignorowany.

To powinno zapewnić dobre obejście:

var data = ctx.Set<Ticket>() 
    .Select(p => new 
     { 
      Ticket = p, 
      Clients = p.Client, 
      LastReplyDate = p.Replies.Max(q => q.DateCreated) 
     }); 

Przede wszystkim, każdy bilet za Klienci będą dostępne bezpośrednio z posesji Clients na anonimowego typu. Ponadto Entity Framework powinien być wystarczająco inteligentny, aby rozpoznać, że wyciągnął całą kolekcję Client dla każdego Ticket, więc wywołanie .Ticket.Client powinno również działać.

+0

Dzięki. To także jest rozwiązanie, o którym myślałem. – Jeroen

+2

+1 za faktyczne dostarczenie rozwiązania :) – bernhof

+0

Powinienem wskazać każdemu, kto czyta to rozwiązanie, że EF nie magicznie wypełnia właściwość nawigacyjną '.Ticket.Client' wraz z obiektami zwróconymi z tą projekcją, więc uzyskuje dostęp do klientów za pośrednictwem obiektu Ticket przeszuka bazę danych ponownie. –

5

Ponieważ Include działa tylko wtedy, gdy bezpośrednio wybierzesz elementy. Po wykonaniu projekcja Include jest ignorowana. Nie powiem ci dlaczego, ale po prostu działa w ten sposób.

+0

Czy uważasz, że Microsoft planuje to zmienić? – billy

+0

plus1 * Nie powiem ci dlaczego, ale po prostu działa w ten sposób. * –

2

Inną możliwością jest użycie rozwiązania StriplingWarrior, ale potem oczyścić dane pośrednie od wyniku końcowego:

var data = ctx.Set<Ticket>() 
    .Select(p => new 
     { 
      Ticket = p, 
      Clients = p.Client, 
      LastReplyDate = p.Replies.Max(q => q.DateCreated) 
     }) 
    .AsEnumerable() 
    .Select(p => new 
     { 
      Ticket = p.Ticket, 
      LastReplyDate = p.LastReplyDate 
     });