2011-10-05 11 views
61

Sto cercando di implementare una query in LINQ che utilizza un join esterno sinistro con più condizioni nella clausola ON.LINQ Join con condizioni multiple nella clausola on

Userò l'esempio dei due seguenti tabelle Progetto (ProjectID, ProjectName) e Task (TaskID, ProjectID, TaskName, completato). Voglio vedere l'elenco completo di tutti i progetti con le rispettive attività, ma solo quelle che sono state completate.

Non riesco a utilizzare un filtro per Completed == true perché questo escluderà tutti i progetti che non hanno attività completate. Invece voglio aggiungere Completed == true alla clausola ON del join in modo che venga mostrato l'elenco completo dei progetti, ma verranno mostrate solo le attività completate. I progetti senza attività completate mostreranno una singola riga con un valore nullo per l'attività.

Ecco le basi della query.

from t1 in Projects 
join t2 in Tasks 
on new { t1.ProjectID} equals new { t2.ProjectID } into j1 
from j2 in j1.DefaultIfEmpty() 
select new { t1.ProjectName, t2.TaskName } 

Come aggiungere && t2.Completed == true alla clausola on?

Non riesco a trovare alcuna documentazione LINQ su come eseguire questa operazione.

risposta

82

Hai solo bisogno di chiamare la proprietà anonima lo stesso su entrambi i lati

on new { t1.ProjectID, SecondProperty = true } equals 
    new { t2.ProjectID, SecondProperty = t2.Completed } into j1 

sulla base dei commenti di @svick, qui è un'altra implementazione che potrebbe avere più senso:

from t1 in Projects 
from t2 in Tasks.Where(x => t1.ProjectID == x.ProjectID && x.Completed == true) 
       .DefaultIfEmpty() 
select new { t1.ProjectName, t2.TaskName } 
+0

che sembra un modo non ovvio per farlo. Non sono sicuro che capirò cosa si suppone di fare. – svick

+1

@svick: l'utilizzo di tipi anonimi consente di aderire su più criteri. Devi solo assicurarti che i nomi delle proprietà corrispondano su entrambi i tipi. Non sai da dove viene la confusione? – Aducci

+0

La confusione è che ha davvero più senso come due uguaglianze unite da 'and', non un'eguaglianza di qualche oggetto" strano ". E per dimostrare il mio punto, il tuo codice è sbagliato. Perché funzioni, dovresti avere 'true' sul lato sinistro e' t2.Complete' sulla destra. – svick

2

È non posso farlo in quel modo La clausola join (e il metodo di estensione Join()) supporta solo equijoins. Questo è anche il motivo, perché usa equals e non ==. E anche se si potesse fare qualcosa del genere, non funzionerebbe, perché join è un join interno, non un join esterno.

20

Qui si va con:

from b in _dbContext.Burden 
join bl in _dbContext.BurdenLookups on 
new { Organization_Type = b.Organization_Type_ID, Cost_Type = b.Cost_Type_ID } equals 
new { Organization_Type = bl.Organization_Type_ID, Cost_Type = bl.Cost_Type_ID }