2012-02-07 12 views
39

Ho una query che combina un join e un gruppo, ma ho un problema. La query è come:LINQ: unione di join e gruppo tramite

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. 
}; 

Come si vede, si unisce la tabella Products con la tabella BaseProducts, e gruppi su un id della tabella Product. Ma nel risultante ProductPriceMinMax, ho anche bisogno di una proprietà della tabella BaseProducts: bp.Name, ma non sa bp.

Qualche idea su cosa sto facendo male?

Grazie!

risposta

64

Una volta che hai fatto questo

group p by p.SomeId into pg 

non hai più accesso alle variabili intervallo utilizzato nella fase iniziale from. Cioè, non puoi più parlare di p o bp, puoi parlare solo di pg.

Ora, pg è un gruppoe così contiene più di un prodotto. Tutti i prodotti in un determinato gruppo pg hanno lo stesso SomeId (poiché è quello che hai raggruppato), ma non so se questo significa che hanno tutti lo stesso BaseProductId.

Per ottenere il nome del prodotto di base, è necessario scegliere un prodotto particolare nel gruppo pg (come si sta facendo con SomeId e CountryCode), e poi iscriverti per 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 
}; 

Detto questo, questo sembra piuttosto insolito e penso che dovresti fare un passo indietro e considerare quello che stai effettivamente cercando di recuperare.

+1

Questo è migliore della nostra soluzione :) Grazie. –

+1

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

+0

@AakashM Grazie. Ma sto recuperando un problema con groupVariable.FirstOrDefault(). Column_name. Quando accedo alla variabile IQueryable Risultato, l'errore si è verificato quale intestazione è ** "entitycommandexecutionexception non è stata gestita dal codice utente" ** with body *** "Si è verificato un errore durante l'esecuzione della definizione del comando. . "*** Non riesco a capire cosa sta succedendo. –

17

L'abbiamo fatto in questo modo:

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: abbiamo utilizzato la versione di AakashM, perché ha una migliore performance

4

Ho incontrato lo stesso problema come te.

I push due tablesresult nell'oggetto t1 e nel gruppo 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 
};