2010-12-10 15 views
6

¿Cuál es la ventaja de escribir un proveedor de LINQ personalizado sobre la escritura de una clase simple que implementa IEnumerable?¿Por qué escribir un proveedor de LINQ personalizado?

Por ejemplo, este quesiton muestra Linq2Excel:

var book = new ExcelQueryFactory(@"C:\Users.xls"); 
var administrators = from x in book.Worksheet<User>() 
        where x.Role == "Administrator" 
        select x; 

Pero ¿cuál es el beneficio de la ejecución "ingenua", como IEnumerable?

+0

No estoy seguro de por qué linq-to-excel se beneficia de IQueryable, pero hay casos en los que hace que el código sea mucho más rápido. – CodesInChaos

Respuesta

11

El propósito de un proveedor de Linq es básicamente "traducir" los árboles de expresión de Linq (que se crean detrás de las escenas de una consulta) en el lenguaje de consulta nativo de la fuente de datos. En los casos en que los datos ya están en la memoria, no necesita un proveedor de Linq; Linq 2 Objects está bien. Sin embargo, si está utilizando Linq para hablar con un almacén de datos externo como un DBMS o una nube, es absolutamente esencial.

La premisa básica de cualquier estructura de consulta es que el motor de la fuente de datos debe hacer la mayor parte del trabajo posible y devolver solo los datos que necesita el cliente. Esto se debe a que se supone que la fuente de datos es la que mejor sabe cómo administrar los datos que almacena, y porque el transporte de datos en red es relativamente costoso en términos de tiempo, por lo que debe minimizarse. Ahora, en realidad, esa segunda parte es "devolver solo los datos solicitados por el cliente"; el servidor no puede leer la mente de su programa y saber lo que realmente necesita; solo puede dar lo que se pide. Aquí es donde un proveedor inteligente de Linq absolutamente destruye una implementación "ingenua". Usando el lado IQueryable de Linq, que genera árboles de expresión, un proveedor de Linq puede traducir el árbol de expresión a, por ejemplo, una declaración SQL que el DBMS utilizará para devolver los registros que el cliente está solicitando en la instrucción Linq. Una implementación ingenua requeriría recuperar TODOS los registros usando una declaración SQL amplia, para proporcionar una lista de objetos en memoria al cliente, y luego todo el trabajo de filtrado, agrupamiento, clasificación, etc. lo realiza el cliente.

Por ejemplo, supongamos que estaba utilizando Linq para obtener un registro de una tabla en el DB por su clave principal. Un proveedor de Linq podría traducir dataSource.Query<MyObject>().Where(x=>x.Id == 1234).FirstOrDefault() en "SELECT TOP 1 * from MyObjectTable WHERE Id = 1234". Eso devuelve cero o uno registros.Una implementación "ingenua" probablemente envíe al servidor la consulta "SELECT * FROM MyObjectTable", luego use el lado IEnumerable de Linq (que funciona en clases en memoria) para hacer el filtrado. En una declaración esperas producir 0-1 resultados de una tabla con 10 millones de registros, ¿cuál de estos crees que harían el trabajo más rápido (o incluso funcionarían sin agotar la memoria)?

7

No necesita escribir un proveedor de LINQ si solo desea utilizar la funcionalidad LINQ-to-Objects (es decir, foreach -like) para su propósito, que en su mayoría funciona contra listas en memoria.

do necesita escribir un proveedor de LINQ si desea analizar el árbol de expresiones de una consulta para traducirlo a otra cosa, como SQL. El ExcelQueryFactory que mencionas parece funcionar con una conexión OLEDB, por ejemplo. Esto posiblemente significa que no necesita cargar todo el archivo de Excel en la memoria al consultar sus datos.

3

En el rendimiento general. Si tiene algún tipo de índice, puede hacer una consulta mucho más rápido de lo que es posible en un simple IEnumerable<T>.

Linq-To-Sql es un buen ejemplo para eso. Aquí transforma la instrucción linq en otra para que la entienda el servidor SQL. Entonces el servidor hará el filtrado, el orden, ... usando los índices y no necesita enviar toda la tabla al cliente, que luego lo hace con linq-to-objects.

Pero hay casos más simples, donde puede ser útil también:

Si usted tiene un índice de árbol sobre el hotel fenomenal Time entonces una consulta gama .Where(x=>(x.Time>=now)&&(x.Time<=tomorrow)) como se puede optimizar mucho, y no es necesario para repetir cada elemento en el enumerable.

1

LINQ proporcionará la ejecución diferida tanto como sea posible para mejorar el rendimiento.

IEnumerable <> y IQueryable <> proporcionarán totalmente diferentes implementaciones de programas. IQueryable proporcionará una consulta nativa construyendo el árbol de expresiones de forma dinámica, lo que proporciona un buen rendimiento, de hecho, es IEnumurable.

http://msdn.microsoft.com/en-us/vcsharp/ff963710.aspx

si no estamos seguros de que podemos utilizar var palabra clave y dinámicamente a inicializar un tipo más adecuado.

Cuestiones relacionadas