2012-09-04 14 views
12

Es Aggregate consulta de VB.NET fatalmente defectuoso cuando se utiliza como la primera cláusula (exterior) de una expresión LINQ con múltiples cláusulas Into porque cada cláusula Into se ejecuta por separado?¿El agregado tiene una falla fatal porque cada cláusula en se ejecuta por separado?

La respuesta "obvia" para SELECT MIN(ZoneMin), MAX(ZoneMin) FROM Plant in LINQ to SQL es

Dim limits = Aggregate p In Plants Select p.ZoneMin Into Min(), Max() 

Sin embargo, esta respuesta realmente lo recupere cada uno de Min y Max (y si se incluyen otras funciones agregadas como Count y Average) en consultas SQL separadas . Esto se puede ver fácilmente en LINQPad.

¿Hay alguna transacción (u otra cosa que haga que estas consultas sean atómicas) que LINQPad no muestra, o esta es una condición de carrera que está por ocurrir? (Y entonces tiene que hacer los trucos que se muestran en la respuesta a la pregunta anterior para forzar una sola consulta que devuelve múltiples agregados).

En resumen, ¿hay una consulta LINQ-to-SQL usando Aggregate que devuelve múltiples agregados funciones en una sola consulta (o al menos "atómica")?

(Me dicen también "evidente" debido a que la respuesta obvia a mí, Aggregate p In Plants Into Min(p.ZoneMin), Max(p.ZoneMin), realmente lo recupere toda la mesa dos veces, incluso cuando optimizado, y luego utiliza el LINQ-a-Entidades Min y Max para obtener el resultado: -()

pensé Aggregate no era VB-específica, pero parece que C# no tiene esta expresión de consulta, por lo que he cambiado el a

+0

Es posible que pueda verificar si las consultas están en una transacción rastreando el servidor SQL en sí, debe mostrarlo (pero no estoy 100% seguro de ello). Sin embargo, si el rendimiento no es una preocupación primordial, es mejor que lea todo el conjunto de datos y lo agregue luego (básicamente, trabajando en una instantánea de los datos). – Alex

+0

Tenga en cuenta que eso es lo que esperaba que mi consulta original 'Into Min (p.ZoneMin)' optimizara, ya que la parte SQL de la consulta ahora es la misma. Quizás JITter aún pueda ver eso, pero LINQPad's/o + no lo hizo. –

+0

Y mientras solo agrega funciones que SQL admite, será preferible hacer la "agrupación por un truco constante" para hacer que la base de datos haga la agregación. –

Respuesta

0

Para responder a mi pregunta más amplia: ¿está roto el Aggregate para producir consultas SQL separadas sin realizar transacciones?

Todos los LINQ pueden hacer que si no ajusta cuidadosamente sus consultas solo resulte en un solo SELECT, y eso puede no ser posible, sin "darse por vencido", obteniendo un resultado mayor en una sola consulta y luego utilizando Linq-to-Objects para agregar o manipular los datos. This 'query' por ejemplo.

Así que, en general, depende del programador asegurarse de que las transacciones se agreguen alrededor de las consultas LINQ que pueden causar varias consultas. Solo necesitamos saber con certeza qué consultas LINQ pueden transformarse en múltiples consultas SQL.

1

Alt. unque no utiliza la palabra clave agregada, puede hacer varias funciones en una sola consulta utilizando la siguiente sintaxis:

Dim query = From book In books _ 
    Group By key = book.Subject Into Group _ 
    Select id = key, _ 
     BookCount = Group.Count, _ 
     TotalPrice = Group.Sum(Function(_book) _book.Price), _ 
     LowPrice = Group.Min(Function(_book) _book.Price), _ 
     HighPrice = Group.Max(Function(_book) _book.Price), _ 
     AveragePrice = Group.Average(Function(_book) _book.Price) 

No parece haber un problema con la implementación cláusula agregada sin embargo. Tenga en cuenta la siguiente consulta de Northwind:

Aggregate o in Orders 
into Sum(o.Freight), 
Average(o.Freight), 
Max(o.Freight) 

Esto emite 3 solicitudes de base de datos. Los dos primeros realizan cláusulas agregadas separadas. El tercero arrastra toda la tabla al cliente y realiza el Max en el cliente a través de Linq to Objects.

+1

Sí, y si lo cambia a 'Agrupar por clave = 0 En grupo' (y suelta el' id = clave, ') se obtiene el truco de" agrupación por constante "descrito en la respuesta a la pregunta que hice referido, permitiendo agregados en toda la tabla. –

+0

En mi muestra, quiero la agrupación. Si lo quieres en toda la mesa, entonces tu truco constante funciona bien. –

+0

I * think * su último punto está relacionado con el tipo 'Freight' y, por alguna razón, Linq opina que 'MAX' de SQL podría devolver un valor diferente al que piensa que' Max' debería devolver. Pero las _3 __separate__ solicitudes de base de datos_ es lo que concierne a mi pregunta. –

Cuestiones relacionadas