2010-07-18 28 views
14

Por lo tanto, estoy tratando de comprender IQueryable<T>. Un tutorial que estoy leyendo sugiere usarlo pero no estoy seguro de por qué. El código simplemente devuelve algunos valores usando LINQ to SQL. Lo he hecho muchas veces en el pasado, pero no he usado IQueryable<T>Tengo problemas para entender IQueryable <T>

¿Por qué usarlo con mis funciones que devuelven más de 1 valor?

Aquí está mi código:

public IQueryable<Items> GetItems() 
    { 
     return from item in db.Items 
       where item.IsActive == true 
       orderby item.ItemNumber 
       select item; 
    } 
+2

gran pregunta. me salvaste horas de investigación. – KyleM

Respuesta

12

IQueryable representa la consulta como un árbol de expresión sin evaluarla en el servidor. Esto le permite especificar un procesamiento adicional antes de generar realmente SQL.

En el caso anterior, esto significa que se pueden hacer cosas con el resultado de llamar GetItems(), y tener la consulta original y el material extra enviado como una sola consulta:

var recentItems = from item in GetItems() 
        where item.Timestamp > somedate 
        select item; 

foreach (var item in recentItems) 
{ 
    // Do something with an active recent item. 
} 

se envía nada al servidor hasta que intentemos consumir el resultado en el ciclo foreach. En ese punto, el proveedor de LINQ-a-SQL evalúa toda la expresión, incluidos los bits generados en GetItems() y los bits especificados después, y emite una única declaración de SQL que selecciona todos los elementos que son activos y recientes.

Para aclarar un tecnicismo, IQueryable<T> es IEnumerable<T>, y su proveedor calcula el SQL final cuando intenta invocar el método GetEnumerator() en él. Puede hacerlo explícitamente llamándolo o implícitamente utilizándolo en una declaración foreach. Además, los métodos de extensión como ToArray() harán uno de estos internamente, produciendo el mismo efecto.

+0

Así que es IEnumerable <> - solo se evalúa 'foreach' o' .ToArray() 'se llama. Entonces, ¿por qué IQueryable <> es diferente de IEnumerable <>? – Enigmativity

+0

Un IQueryable * es * un IEnumerable, y ambos pueden proporcionar una colección de límite tardío. Pero, el punto de IQuerable en L2S es la ejecución de SQL retrasada. Con IQueryable, puede seguir agregando elementos de consulta, como las condiciones de .Where() hasta el momento en que finalmente comience a enumerar. En ese punto, IQueryable finalmente ejecuta la consulta SQL y llena una colección para que usted la enumere. Si está seguro de haber terminado con su consulta y de que nada que llame a su método necesita agregarle más condiciones, entonces puede decidir simplemente llamar a .ToList() y terminar sin devolver un IQuerable. – mattmc3

+0

'IQueryable ' implementa la interfaz 'IEnumerable ', por lo que un 'IQueryable' se puede utilizar como un' IEnumerable'. La gran diferencia es que IQueryable es una definición de una operación en lugar de la operación (código compilado) en sí misma. Esto permite que el proveedor de LINQ a SQL analice esto y lo convierta a SQL. Esto sería (casi) imposible de hacer con el código compilado normal. – Steven

5

Un IQueryable (antes de que se enumere) no es el resultado en sí mismo sino la lógica utilizada para devolver esos resultados.

Para utilizar un ejemplo de LINQ2SQL ... imagine que devuelve un IQueryable of Clients. Bajo el capó que no va a ser una lista de clientes (hasta que ToList()) pero se podía comprender ser una consulta SQL, así:

SELECT * FROM [Clients] 

Ahora bien, esto es muy útil porque no hemos golpeado la base de datos todavía! Lo que permite decir cuando ese IQueriable regresa queremos refinarlo a clientes llamados "Bob" que podemos hacer:

var clients = GetClients().Where(c => c.Name == "Bob"); 

Ahora el IQueriable se parece a esto bajo el capó:

SELECT * FROM [Clients] WHERE Name = 'Bob'. 

Ahora, cuando Hago clients.ToList(), esa consulta se ejecutará, se golpeará la base de datos, y tengo una lista de clientes llamada bob sin tener que haber seleccionado todos los clientes y luego rastrearlos en la memoria, o realizar 2 hits de bases de datos separados.

Para obtener un ejemplo de esto mordiéndolo en la parte posterior, intente acceder a elementos secundarios cuando su contexto de datos se haya salido del alcance (por ejemplo, ejecute su selección dentro de una instrucción using). Aquí es donde las opciones de carga son útiles, en LINQ2SQL.

Espero que ayude

+0

Entonces IEnumerable <> - solo se evalúa '.ToList()' se llama. Entonces, ¿por qué IQueryable <> es diferente de IEnumerable <>? – Enigmativity

+0

Sus datos aún son un árbol de expresiones antes de enumerar IQueryable ... En el ejemplo de LINQ2SQL no puede tener SELECT * FROM Clients como IEnumerable ya que es una expresión y no contiene valores enumerables hasta que se ejecuta la consulta. Si bien sigue siendo un IQueryable no enumerado, puede agregar cláusulas que hagan crecer el árbol de expresiones. – jdoig

Cuestiones relacionadas