2012-05-09 12 views
12

Ejemplo:¿Realmente necesito usar AsQueryable() en la colección? código

List<Student> Students = new List<Student>() 
{ 
    new Student(101, "Hugo", "Garcia", new List<int>() { 91, 88, 76, 93 }), 
    new Student(102, "Rick", "Adams", new List<int>() { 70, 73, 66, 90 }), 
    new Student(103, "Michael", "Tucker", new List<int>() { 73, 80, 75, 88 }), 
    new Student(104, "Fadi", "Fakhouri", new List<int>() { 82, 75, 66, 84 }), 
    new Student(105, "Peter", "Barrows", new List<int>() { 67, 78, 70, 82 }) 
}; 

var query = from student in Students 
      where student.Marks.AsQueryable().All(m => m > 70) 
      select student; 

foreach (Student student in query) 
{ 
    Console.WriteLine("{0} {1}<br />", student.FirstName, student.LastName); 
} 

Pero si cambio de la consulta a

var query = from student in Students 
      where student.Marks.All(m => m > 70) 
      select student; 

Esto también funciona y produce el mismo resultado, así que cuál es la diferencia?

+0

Una pregunta similar en [ 'AsEnumerable'] (http://stackoverflow.com/questions/3389855/am-i-misunderstanding-linq-to-sql-asenumerable) – nawfal

Respuesta

7

IQueryable es necesario/recomendado para objetos procedentes de fuente remota (como la base de datos).

Para en colecciones de memoria no sirve de nada.

AsQueryable se utiliza cuando se va a construir el árbol de expresiones.

Puedo pensar en el escenario donde mejor se ajuste. En su ejemplo, supongamos que necesita información de la base de datos basada en la identificación del estudiante.

Ahora el estudiante está en la colección de memoria. Debe activar la consulta de la base de datos en función de la identificación del estudiante.

var studentList = Students.Select(s => s.Id).AsQueryAble().Select(i => remoteDBProvider.GetInfo(i)); 

Cualquier operación adicional en el studentList será invocado desde la interfaz IQueryable (expresión de consulta), y se ha podido recuperar sólo aquellos registros de la fuente de datos, que debe ser devuelto como resultado de la consulta final (tanto tiempo como fuente de datos, de retorno valor de remoteDBProvider.GetInfo en el ejemplo, admite QueryProvider).

+5

@BorisB. Eso simplemente no es cierto. [Enumerable.Select] (http://msdn.microsoft.com/en-us/library/bb548891.aspx) también utiliza la ejecución diferida. La diferencia es que Queryable acepta el lambda como una expresión. Esto permite que un proveedor de consultas inspeccione la expresión y la traduzca a algo (potencialmente) más eficiente, p. una consulta SQL. Cualquier proyección o filtrado tendrá lugar en la base de datos en lugar de en la aplicación, aprovechando el código nativo de la base de datos. Pero para las colecciones en memoria no hace la diferencia. –

+0

@NielsvanderRest: Tiene razón, comentario eliminado ya que es engañoso (o simplemente falso). Sin embargo, 'AsQueryable' todavía se usa incluso para colecciones de memoria, ya que su método de extensión' Select' acepta una 'Expresión ', que le permite analizarla o modificarla. Un escenario en el que puedo pensar es usar la colección en memoria envuelta en un 'IQueryable' como una forma para que una capa que no reconoce la persistencia envíe una consulta como un AST a una capa consciente de la persistencia. –

2

Tiene que ver cómo se construye el árbol de expresiones. Mira esto:

AsQueryable es un método que permite la consulta para ser convertido en un instancia de IQueryable. Cuando utiliza el operador AsQueryable en una consulta existente y aplica otras transformaciones, como aplicar un filtro o especificar un orden de clasificación, esas declaraciones lambda son convertidas en árboles de Expresión. Dependiendo del proveedor que esté usando , los árboles de expresiones se convertirán en la sintaxis específica del dominio y luego se ejecutarán. En el caso de Linq a proveedor de SQL, el árbol de expresión se convertiría a SQL y se ejecutaría en el servidor SQL. Sin embargo, si utiliza el operador AsQueryable en una consulta que no implementa IQueryable y solo implementa IEnumerable, cualquier transformación que aplique en la consulta caería automáticamente en la especificación IEnumerable. Lo que esto significa es etiquetar una consulta con AsQueryable, usted obtiene los beneficios de ambos Linq a SQL y Linq para la implementación de objetos. Si su consulta actual implementa IQueryable, la consulta se convierte a SQL por el proveedor de Linq a SQL, , de lo contrario, la consulta se ejecuta en la memoria en el código IL de forma.

Referencia here

1

En el caso de que su List<Student>, que no hace ninguna diferencia, ya que el IQueryable<T> devuelto será usar los mismos métodos para realizar consultas como si no hubiera usado AsQueryable() en absoluto.

Algunos métodos esperan un parámetro IQueryable<T>.Creo que el método de extensión AsQueryable() es principalmente útil para esos escenarios, cuando necesitas pasar un IQueryable<T> pero solo tienes un IEnumerable<T>.

MSDN dice sobre AsQueryable: directamente

Si el tipo de fuente implementa IQueryable<T>, AsQueryable<TElement>(IEnumerable<TElement>) lo devuelve. De lo contrario, devuelve un IQueryable<T> que ejecuta consultas por llamando a los métodos de operador de consulta equivalentes en Enumerable en lugar de en Queryable.

Por lo que significa en su caso (List<T> no implementa IQueryable<T>), que realmente no es necesario AsQueryable.

Cuestiones relacionadas