2011-08-31 12 views
8

Me gustaría traducir el siguiente código SQL en LINQ:devolver múltiples columnas agregadas en LINQ

SELECT 
    (Select count(BidID)) as TotalBidNum, 
    (Select sum(Amount)) as TotalBidVal 
FROM Bids 

He intentado esto:

from b in _dataContext.Bids 
select new { TotalBidVal = b.Sum(p => p.Amount), TotalBidNum = b.Count(p => p.BidId) } 

pero consigo un error pujas" no contiene una definición para "Suma" y no se pudo encontrar ningún método de extensión "Suma" aceptando un primer argumento de tipo "Ofertas"

¿Cómo puedo hacer esto en LINQ?

Gracias

finales:

La respuesta final fue:

var ctx = _dataContext.Bids; 

var itemsBid = (from b in _dataContext.Bids 
       select new { TotalBidVal = ctx.Sum(p => p.Amount), TotalBidNum = ctx.Count() }).First(); 

Respuesta

6

Se puede probar esto. La variable b es una entidad (para cada iteración) mientras que ctx es un conjunto de entidades que tiene los métodos de extensión que necesita.

var ctx = _dataContext.Bids; 

var result = ctx.Select(x => new {TotalBidVal = ctx.Sum(p => p.Amount),TotalBidNum = ctx.Count(p => p.BidId)}).First(); 
+0

Eso solucionó el error (aunque parece como un paso innecesario - ¿por qué es ¿Lo necesitaba?). Hubo un problema con mi Cuenta (p => p.BidID) - un error que p.BidID no era booleano. Lo reemplacé con Count() y ahora la consulta devuelve la suma correcta y el recuento, pero no como una sola fila. La misma fila una y otra vez. Supongo que tantas veces como filas hay en la tabla de ofertas. ¿Cómo puedo devolver una sola fila como en mi consulta SQL original? – BKahuna

+0

@BKahuna su consulta dice "de b en _dataContext.Bids" eso es una iteración. y no obtendrás un resultado aunque intentes calcular solo la suma y el recuento. Puede finalizar la expresión lambda llamando a First(). que te dará solo un resultado como lo hice. – scartag

+0

@BKahuna por favor, desplácese hasta el final de mi respuesta y vea la última llamada que realizo. llamo al método First() que asegurará que obtenga una sola fila de vuelta (el sql generado es Top (1)) – scartag

1

aquí es una alternativa a la solución de scartag:

(from b in _dataContext.Bids.Take(1) 
select new 
{ 
    TotalBidVal = _dataContext.Bids.Sum(p => p.Amount), 
    TotalBidNum = _dataContext.Bids.Count() 
}).Single(); 

Aunque no hay una verdadera razón por la que no puede decir:

var result = new 
{ 
    TotalBidVal = _dataContext.Bids.Sum(p => p.Amount), 
    TotalBidNum = _dataContext.Bids.Count() 
}; 

golpea la base de datos dos veces, pero su muy legible

+0

Esto también devuelve la respuesta correcta, ¡gracias! – BKahuna

+0

He editado con una solución más pragmática – saus

17

Puede escribir esta consulta usando GroupBy. La expresión Lambda es la siguiente:

var itemsBid = db.Bids 
        .GroupBy(i => 1) 
        .Select(g => new 
        { 
          TotalBidVal = g.Sum(item => item.Amount), 
          TotalBidNum = g.Count(item => item.BidId) 
        }); 
+1

Exactamente lo que necesitaba (aunque en el antiguo y simple linq, no linq2SQL o EF). – jahu

+0

simple. Me gusta. – Oak

+0

Esto es simple, pero el truco. Por cierto, me gustaría saber el propósito del operador ".GroupBy (i => 1)". ¿Por qué necesitamos eso? –

0

Puede hacerlo utilizando el Aggregate Clause.

Aggregate t In _dataContext.Bids 
Into TotalBidNum = Count(BidID), 
    TotalBidVal = Sum(Amount) 

Si está utilizando Fx4 + o un archivo DLL de extensión para Fx2, también se puede benfit del paralelismo utilizando

Aggregate t In _dataContext.Bids.AsParallel 
Cuestiones relacionadas