2012-02-07 12 views
39

Tengo una consulta que combina un join y un grupo, pero tengo un problema. La consulta es como:LINQ: combine join y group por

var result = from p in Products       
join bp in BaseProducts on p.BaseProductId equals bp.Id      
group p by p.SomeId into pg       
select new ProductPriceMinMax { 
     SomeId = pg.FirstOrDefault().SomeId, 
     CountryCode = pg.FirstOrDefault().CountryCode, 
     MinPrice = pg.Min(m => m.Price), 
     MaxPrice = pg.Max(m => m.Price), 
     BaseProductName = bp.Name <------ can't use bp. 
}; 

Como se ve, se une a la mesa de los productos con la tabla BaseProducts y grupos en un id de la tabla del producto. Pero en el ProductPriceMinMax resultante, también necesito una propiedad de la tabla BaseProducts: bp.Name, pero no sabe bp.

¿Alguna idea de lo que estoy haciendo mal?

Gracias!

Respuesta

64

Una vez que haya hecho esto

group p by p.SomeId into pg 

ya no tienen acceso a las variables de rango usados ​​en la inicial from. Es decir, ya no puede hablar sobre p o bp, solo puede hablar de pg.

Ahora, pg es un grupoy así contiene más de un producto. Todos los productos en un grupo dado pg tienen el mismo SomeId (ya que eso es lo que agruparon), pero no sé si eso significa que todos tienen el mismo BaseProductId.

Para obtener el nombre del producto de base, usted tiene que escoger un producto en particular en el grupo pg (como lo están haciendo con SomeId y CountryCode), y luego unirse a BaseProducts.

var result = from p in Products       
group p by p.SomeId into pg       
// join *after* group 
join bp in BaseProducts on pg.FirstOrDefault().BaseProductId equals bp.Id   
select new ProductPriceMinMax { 
     SomeId = pg.FirstOrDefault().SomeId, 
     CountryCode = pg.FirstOrDefault().CountryCode, 
     MinPrice = pg.Min(m => m.Price), 
     MaxPrice = pg.Max(m => m.Price), 
     BaseProductName = bp.Name // now there is a 'bp' in scope 
}; 

Dicho esto, esto se ve bastante inusual y creo que debe dar un paso atrás y considerar lo que realmente está tratando de recuperar.

+1

Esto es mejor que nuestra solución :) Gracias. –

+1

mire http://stackoverflow.com/a/2877012/1923685 –

+0

@AakashM Gracias. Pero estoy obteniendo un problema con groupVariable.FirstOrDefault(). Column_name. Cuando voy a acceder a la variable IQueryable Result, se produce el error cuyo encabezado es ** "entitycommandexecutionexception no fue manejado por el código de usuario" ** con cuerpo *** "Ocurrió un error al ejecutar la definición del comando. Consulte la excepción interna para obtener detalles . "*** No puedo entender lo que está sucediendo. –

17

Lo hicimos así:

from p in Products       
join bp in BaseProducts on p.BaseProductId equals bp.Id      
where !string.IsNullOrEmpty(p.SomeId) && p.LastPublished >= lastDate       
group new { p, bp } by new { p.SomeId } into pg  
let firstproductgroup = pg.FirstOrDefault() 
let product = firstproductgroup.p 
let baseproduct = firstproductgroup.bp 
let minprice = pg.Min(m => m.p.Price) 
let maxprice = pg.Max(m => m.p.Price) 
select new ProductPriceMinMax 
{ 
SomeId = product.SomeId, 
BaseProductName = baseproduct.Name, 
CountryCode = product.CountryCode, 
MinPrice = minprice, 
MaxPrice = maxprice 
}; 

EDIT: se utilizó la versión de AakashM, porque tiene un mejor rendimiento

4

me encontré con el mismo problema que tú.

Empujo dos tablesresult en t1 objeto y grupo t1.

from p in Products       
    join bp in BaseProducts on p.BaseProductId equals bp.Id 
    select new { 
    p, 
    bp 
    } into t1 
group t1 by t1.p.SomeId into g 
select new ProductPriceMinMax { 
    SomeId = g.FirstOrDefault().p.SomeId, 
    CountryCode = g.FirstOrDefault().p.CountryCode, 
    MinPrice = g.Min(m => m.bp.Price), 
    MaxPrice = g.Max(m => m.bp.Price), 
    BaseProductName = g.FirstOrDefault().bp.Name 
};