2012-03-14 15 views
5

Attualmente sto cercando di capire alcuni dei fondamenti con LINQ. Sto usando LINQPad per interrogare l'origine OData di Netflix.Query lambda LINQ 'select' non funziona con oData

Fonte:http://odata.netflix.com/v2/Catalog/

io non riesco a selezionare singole proprietà quando si utilizza una query lambda - la query di comprensione funziona perfettamente. Ho trovato uno snippet di codice che esegue una query più complessa utilizzando lambdas sul sorgente NetDlix oData e sembra funzionare bene per restituire una proprietà dell'entità.

// works fine 
var compQuery = from t in Titles 
       where t.ReleaseYear == 2007 
       select new { t.Name }; 
compQuery.Dump(); 



// fails: "Can only specify query options (orderby, where, take, skip) after last navigation." 
var lambdaQuery = Titles 
      .Where(t => t.ReleaseYear == 2007) 
      .Select(t => t.Name); 

lambdaQuery.Dump(); 


// works fine - found on SO. 
var lambdaQuery2 = People 
    .Expand("TitlesActedIn") 
    .Where(p => p.Name == "George Lucas") 
    .First() 
    .TitlesActedIn.Select(t => t.ShortName);    

lambdaQuery2.Dump(); 

Qualcuno potrebbe far luce sul motivo per cui la query base lambda non riesce quando gli viene chiesto di restituire una proprietà?

risposta

4

Prova questo- è quello che è in realtà equivalente al vostro primo:

// fails: "Can only specify query options (orderby, where, take, skip) after last navigation." 
var lambdaQuery = Titles 
      .Where(t => t.ReleaseYear == 2007) 
      .Select(t => new { t.Name }); 

lambdaQuery.Dump(); 
+0

ahhh, l'ho provato ora e funziona! - Quello che non capisco è come l'altra query lambda (persone) non mi imponga di creare un tipo anonimo per la proiezione? – Dal

+0

Poiché si chiama '.First()' su di esso, che materializza i risultati, esso assorbe l'intero record e quindi seleziona le proprietà in memoria sul client. –

+0

Spiegheresti perché richiede l'uso di un tipo anonimo? Grazie –

12

OData non dispone di supporto per la proiezione di proprietà - si può ovviare a questo però:

var lambdaQuery = Titles 
      .Where(t => t.ReleaseYear == 2007) 
      .Select(x=> new { x.Name }) 
      .AsEnumerable() 
      .Select(t => t.Name); 

L'utilizzo di AsEnumerable() impone l'esecuzione dell'ultima parte della query nel contesto Linq-to-Objects (anziché una query OData) in cui la proiezione funziona correttamente.

+0

Grazie, funziona - Ho trovato alcune ulteriori informazioni qui riguardo AsEnumerable - http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataservices/thread/d427cbf6-4d8a-42ee-9799-d5ca79e581dc – Dal

+0

Vorrei poterlo testare dal lavoro (Netflix bloccato qui) ma la prima proiezione è effettivamente necessaria? Sembra un po 'ridondante qui. –

+0

@JeffMercado: Secondo Odata (e il link nei commenti sopra) una proiezione di odata invierà l'entità stessa, ma tralasciando le proprietà che non sono necessarie - quindi è meglio che le prestazioni lascino questo per ridurre la quantità di dati che vanno oltre il filo – BrokenGlass

0

Utilizzando le risposte fornite, ho eseguito alcuni test e trovato alcune cose interessanti per quanto riguarda il tempo di esecuzione:

// Avg Execution Time: 5 seconds 
var query1 = Titles 
      .Where(t => t.ReleaseYear == 2007) 
      .Select(t => new {t.Name});  
query1.Dump(); 


// Avg Execution Time: 15 seconds 
var query2 = Titles 
      .Where(t => t.ReleaseYear == 2007) 
      .AsEnumerable() 
      .Select(t => t.Name);  
query2.Dump(); 

Così Ho ragione di pensare che nella query 1, solo la proprietà 'Nome' viene restituito ? Mentre nella query 2, il metodo 'AsEnumerable()' sta riportando l'entità con tutti i valori delle proprietà, quindi un tempo di esecuzione più lungo?

+0

Sì, i dati trasferiti sono molto più grandi per query2 E poiché si interrogano intere entità, vengono tracciati in base al contesto. – springy76