2008-09-18 8 views
5

Hablando como un no-programador de C# con experiencia, estoy curioso en cuanto a la semántica de evaluación de consultas LINQ como las siguientes:¿LINQ-to-SQL admite consultas compostables?

var people = from p in Person 
      where p.age < 18 
      select p 

var otherPeople = from p in people 
        where p.firstName equals "Daniel" 
        select p 

Suponiendo que Person es una entidad de ADO que define los campos age y firstName, lo ¿Esto lo haría desde el punto de vista de una base de datos? Específicamente, ¿se ejecutaría la consulta people para producir una estructura en memoria, que luego sería consultada por la consulta otherPeople? ¿O la construcción de otherPeople simplemente extraerá los datos con respecto a la consulta de people y luego generará una nueva consulta con base de datos? Entonces, si iteraba sobre estas dos consultas, ¿cuántas sentencias SQL se ejecutarían?

Respuesta

12

Son composable. Esto es posible porque las consultas LINQ son en realidad expresiones (código como datos), que los proveedores de LINQ como LINQ-to-SQL pueden evaluar y generar el SQL correspondiente.

Debido a que las consultas de LINQ se evalúan con holgazanería (por ejemplo, no se ejecutarán hasta que itere sobre los elementos), el código que mostró no tocará realmente la base de datos. No hasta que itere sobre otra persona o personas, SQL se generará y ejecutará.

1

people y otherPeople contienen objetos del tipo IQueryable<Person>.

Si itera sobre ambos, separadamente, se ejecutarán dos consultas. Si solo itera sobre otherPeople, ejecutará la consulta esperada, con dos cláusulas where.

Si lo hace .ToList() en people y utiliza el List<Person> devuelto en la segunda consulta en lugar de la gente, se convierte en LINQ a objetos y no se ejecuta ningún SQL.

Este comportamiento se conoce como ejecución diferida. Es decir, no se realiza ninguna consulta hasta que se necesite. Antes de la ejecución, son solo árboles de expresiones que se manipulan para formular la consulta final.

0

Ambas consultas se ejecutarán cuando intente acceder a los resultados finales. Puede intentar ver el SQL original generado a partir de las propiedades del objeto DataContext.

3

Sí, la consulta resultante está compuesta. Incluye la cláusula where completa. Active el perfil SQL y pruébelo para verlo usted mismo.

Linq hace esto a través de árboles de expresión. La primera instrucción linq produce un árbol de expresiones; no ejecuta la consulta. La segunda instrucción linq se basa en el árbol de expresiones creado por el primero. La declaración solo se ejecuta cuando enumera la colección resultante.

3
var people = from p in Person 
      where p.age < 18 
      select p 

se traduce en:

SELECT [t0].[PersonId], [t0].[Age], [t0].[FirstName] 
FROM [dbo].[Person] AS [t0] 
WHERE [t0].[Age] < @p0 

donde @ p0 es enviado a través como 18

var otherPeople = from p in people 
        where p.firstName equals "Daniel" 
        select p 

Traduce a:

SELECT [t0].[PersonId], [t0].[Age], [t0].[FirstName] 
FROM [dbo].[Person] AS [t0] 
WHERE [t0].[FirstName] = @p0 

donde @ p0 es enviado a través de " Daniel "

var morePeople = from p1 in people 
       from p2 in otherPeople 
       where p1.PersonId == p2.PersonId 
       select p1; 

se traduce en:

SELECT [t0].[PersonId], [t0].[Age], [t0].[FirstName] 
FROM [dbo].[Person] AS [t0], [dbo].[Person] AS [t1] 
WHERE ([t0].[PersonId] = [t1].[PersonId]) AND ([t0].[Age] < @p0) AND ([t1].[FirstName] = @p1) 

donde @ p0 es 18, @ p1 es "Daniel"

En caso de duda, llame a la ToString() en su IQueryable o dar una TextWriter a la Propiedad del registro de DataContext.

Cuestiones relacionadas