简体   繁体   中英

LINQ - How to use distinct with order by?

I want to do a distinct on this:

query = from acao in query
  join itemAuditoria in Session.Query<ItemAuditoria>() on acao.Id equals itemAuditoria.Acao.Id
  join auditoria in Session.Query<Auditoria>() on itemAuditoria.Auditoria.Id equals auditoria.Id
  join maquina in Session.Query<Maquina>() on auditoria.Maquina.Id equals maquina.Id
  orderby maquina.Nome, acao.Numero
  select acao;

But if I try putting a distinct at the end of the query like this:

query = (from acao in query
  join itemAuditoria in Session.Query<ItemAuditoria>() on acao.Id equals itemAuditoria.Acao.Id
  join auditoria in Session.Query<Auditoria>() on itemAuditoria.Auditoria.Id equals auditoria.Id
  join maquina in Session.Query<Maquina>() on auditoria.Maquina.Id equals maquina.Id
  orderby maquina.Nome, acao.Numero
  select acao).Distinct();

then I get this error:

ORDER BY items must appear in the select list if SELECT DISTINCT is specified.

Not sure about the performance impact compared to the answer in OP's comments, but this could be subqueried for readability!

query =
    (from distinctAcao in
        (from acao in query
        join itemAuditoria in Session.Query<ItemAuditoria>() on acao.Id equals itemAuditoria.Acao.Id
        join auditoria in Session.Query<Auditoria>() on itemAuditoria.Auditoria.Id equals auditoria.Id
        join maquina in Session.Query<Maquina>() on auditoria.Maquina.Id equals maquina.Id
        select acao).Distinct()
    orderby maquina.Nome, distinctAcao.Numero
    select distinctAcao);

edit:

So sorry for overlooking that it didn't compile - it did in my head ;) Corrections on the way!

Because we're doing subquery here, the result of which is a list of acao items which don't have a Nome field, we cannot sort by it after we leave the subquery. Therefore we can either:

  1. Sort inside subquery, then eliminate duplicates.

     query=( from distinctAcao in ( from acao in query join itemAuditoria in Session.Query<ItemAuditoria>() on acao.Id equals itemAuditoria.Acao.Id join auditoria in Session.Query<Auditoria>() on itemAuditoria.Auditoria.Id equals auditoria.Id join maquina in Session.Query<Maquina>() on auditoria.Maquina.Id equals maquina.Id orderby maquina.Nome,acao.Numero select acao ).Distinct() select distinctAcao ); 

    Result: sorted, unique acao s list

    Cons: first sorting, then filtering might impact performance

  2. Return a better, combined object from the subquery, which will expose new fields from joined tables.

     query2=( from distinctMix in ( from acao in query join itemAuditoria in Session.Query<ItemAuditoria>() on acao.Id equals itemAuditoria.Acao.Id join auditoria in Session.Query<Auditoria>() on itemAuditoria.Auditoria.Id equals auditoria.Id join maquina in Session.Query<Maquina>() on auditoria.Maquina.Id equals maquina.Id select new { Id=acao.Id,Numero=acao.Numero,NomeFromMaquina=maquina.Nome } ).Distinct() orderby distinctMix.NomeFromMaquina,distinctMix.Numero select distinctMix ); 

    Result: quickly sorted, unique ( acao +more) list

    Cons: returned object will be of different type than original query that was used to iterate acao s, so assigning query=from acao in query select new { /* something else than acao */ }; won't work (hence query2 in this code example)

  3. Use answer from OP's comments :)

PS

This time the code compiles for sure - test code available at https://ideone.com/mDRRle :>

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