2012-03-14 22 views
5

Actualmente estoy tratando de comprender algunos de los fundamentos con LINQ. He estado usando LINQPad para consultar el origen de Netflix OData.LINQ La consulta Lambda 'select' no funciona con oData

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

Me parece que no puede seleccionar las propiedades individuales cuando se utiliza una consulta lambda - la consulta comprensión funciona perfectamente. Encontré un fragmento de código que realiza una consulta más compleja usando lambdas en la fuente de NetFlix oData, y parece funcionar bien para devolver una propiedad de la entidad.

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

¿Alguien podría arrojar alguna luz sobre por qué está fallando cuando se le preguntó la consulta básica lambda para devolver una propiedad?

Respuesta

4

Pruebe esto: que es lo que es en realidad equivalente a la primera de ellas:

// 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, lo intenté ahora y funciona! - Lo que no entiendo es ¿cómo la otra consulta lambda (personas) no requiere que cree un tipo anónimo para la proyección? – Dal

+0

Como llama a '.First()' en él, lo que materializa los resultados, absorbe todo el registro y luego selecciona las propiedades en la memoria del cliente. –

+0

¿Podría explicar por qué requiere el uso de un tipo anónimo? Gracias –

12

OData no tiene soporte para la proyección de propiedades - puede solucionar esto, sin embargo:

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

El uso de AsEnumerable() obliga a ejecutar la última parte de la consulta en el contexto Linq-to-Objects (en lugar de una consulta OData) donde la proyección funciona bien.

+0

Gracias, eso funciona - He encontrado más información aquí con respecto a AsEnumerable - http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataservices/thread/d427cbf6-4d8a-42ee-9799-d5ca79e581dc – Dal

+0

Desearía poder probar esto desde el trabajo (Netflix está bloqueado aquí), pero ¿es realmente necesaria la primera proyección? Parece un poco redundante aquí. –

+0

@JeffMercado: según Odata (y el enlace en los comentarios anteriores) una proyección de odata enviará a la entidad misma, pero dejando de lado las propiedades que no son necesarias, por lo que es mejor para el rendimiento dejar esto para reducir la cantidad de datos que van por el cable – BrokenGlass

0

El uso de las respuestas dadas, he corrió algunas pruebas y encontrado algunas cosas interesantes en cuanto a tiempo de ejecución:

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

Así que estoy en lo cierto al pensar que en la consulta 1, sólo se devuelve la propiedad 'Nombre' ? Mientras que en la consulta 2, el método 'AsEnumerable()' está devolviendo la entidad con todos los valores de propiedad, por lo tanto, ¿tiempo de ejecución más largo?

+0

Sí, los datos transferidos son mucho más grandes para query2 Y dado que está consultando entidades enteras, el contexto los rastrea. – springy76