简体   繁体   中英

LINQ Group By multiple table Inner Join and aggregate function

I have the following Linq to EF query:

from envelope in ENVELOPEs.AsNoTracking()
join spool in SPOOLs.AsNoTracking() on envelope.SPOOL_ID equals spool.SPOOL_ID
join extract in EXTRACTs.AsNoTracking() on spool.EXTRACT_ID equals extract.EXTRACT_ID
join extractProfile in EXTRACT_PROFILE.AsNoTracking() on extract.EXTRACT_PROFILE_ID equals extractProfile.EXTRACT_PROFILE_ID
join box in BOXes.AsNoTracking() on envelope.BOX_ID equals box.BOX_ID
join pallet in PALLETs.AsNoTracking() on box.PALLET_ID equals pallet.PALLET_ID
join fakeCap in FAKECAPs.AsNoTracking() on envelope.FAKECAP_ID equals fakeCap.FAKECAP_ID
join envWeightRange in ENVELOPE_WEIGHT_RANGE.AsNoTracking() on envelope.ENV_WEIGHT_RANGE_ID equals envWeightRange.ENV_WEIGHT_RANGE_ID
join ptype in PTYPEs.AsNoTracking() on spool.PTYPE_ID equals ptype.PTYPE_ID
join envType in ENVTYPEs.AsNoTracking() on ptype.ENVTYPE_ID equals envType.ENVTYPE_ID
join boxType in BOXTYPEs.AsNoTracking() on envType.BOXTYPE_ID equals boxType.BOXTYPE_ID
where spool.JSHEET_ID == 8
orderby envWeightRange.ENV_WEIGHT_RANGE_CODE,
    fakeCap.FAKECAP_DEST_TARIF
group new { envelope, envType } by
new 
{ 
    fakeCap.FAKECAP_DEST_TARIF,
    envWeightRange.ENV_WEIGHT_RANGE_CODE    
} into grouped
select new
{
    FAKECAP_DEST_TARIF = grouped.Key.FAKECAP_DEST_TARIF,
    ENV_WEIGHT_RANGE_CODE = grouped.Key.ENV_WEIGHT_RANGE_CODE,
    ENVTYPE_COD_OMOLOG = grouped.Max(item => item.ENVTYPE_COD_OMOLOG), // Error: ENVTYPE_COD_OMOLOG not defined
    TOTALE_BUSTE = grouped.Count()
}

It fails saying that filed ENVTYPE_COD_OMOLOG is not defined. (Sorry I would have wished to paste there the whole exception, but it's in not inenglish ue to OS locale settings).

However if I Include the field ENVTYPE_COD_OMOLOG in the group by without accessing it with aggregate functions, it works perfectly:

from envelope in ENVELOPEs.AsNoTracking()
join spool in SPOOLs.AsNoTracking() on envelope.SPOOL_ID equals spool.SPOOL_ID
join extract in EXTRACTs.AsNoTracking() on spool.EXTRACT_ID equals extract.EXTRACT_ID
join extractProfile in EXTRACT_PROFILE.AsNoTracking() on extract.EXTRACT_PROFILE_ID equals extractProfile.EXTRACT_PROFILE_ID
join box in BOXes.AsNoTracking() on envelope.BOX_ID equals box.BOX_ID
join pallet in PALLETs.AsNoTracking() on box.PALLET_ID equals pallet.PALLET_ID
join fakeCap in FAKECAPs.AsNoTracking() on envelope.FAKECAP_ID equals fakeCap.FAKECAP_ID
join envWeightRange in ENVELOPE_WEIGHT_RANGE.AsNoTracking() on envelope.ENV_WEIGHT_RANGE_ID equals envWeightRange.ENV_WEIGHT_RANGE_ID
join ptype in PTYPEs.AsNoTracking() on spool.PTYPE_ID equals ptype.PTYPE_ID
join envType in ENVTYPEs.AsNoTracking() on ptype.ENVTYPE_ID equals envType.ENVTYPE_ID
join boxType in BOXTYPEs.AsNoTracking() on envType.BOXTYPE_ID equals boxType.BOXTYPE_ID
where spool.JSHEET_ID == 8
orderby envWeightRange.ENV_WEIGHT_RANGE_CODE,
    fakeCap.FAKECAP_DEST_TARIF
group new { envelope, envType } by
new 
{ 
    fakeCap.FAKECAP_DEST_TARIF,
    envWeightRange.ENV_WEIGHT_RANGE_CODE,
    envType.ENVTYPE_COD_OMOLOG
} into grouped
select new
{
    FAKECAP_DEST_TARIF = grouped.Key.FAKECAP_DEST_TARIF,
    ENV_WEIGHT_RANGE_CODE = grouped.Key.ENV_WEIGHT_RANGE_CODE,
    ENVTYPE_COD_OMOLOG = grouped.Key.ENVTYPE_COD_OMOLOG,
    TOTALE_BUSTE = grouped.Count()
}

In that query, grouped is an IGrouping<TKey,T> where:

  • T is the projected type, in this case new { envelope, envType }

  • TKey is the grouping key, in this case (without including ENVTYPE_COD_OMOLOG ):

     new { fakeCap.FAKECAP_DEST_TARIF, envWeightRange.ENV_WEIGHT_RANGE_CODE } 

An IGrouping<TKey,T> , apart from having a property TKey Key can also be viewed as an IEnumerable<T> . That means to get the max ENVTYPE_COD_OMOLOG from each group, you will need to change your select in the following way (The Max will apply over a sequence of T ):

select new
{
    FAKECAP_DEST_TARIF = grouped.Key.FAKECAP_DEST_TARIF,
    ENV_WEIGHT_RANGE_CODE = grouped.Key.ENV_WEIGHT_RANGE_CODE,
    ENVTYPE_COD_OMOLOG = grouped.Max(item => item.envType.ENVTYPE_COD_OMOLOG),
    TOTALE_BUSTE = grouped.Count()
}

That way you don't need to group by ENVTYPE_COD_OMOLOG and can still get the maximum per group in the result.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM