Próbuję zaimplementować zapytanie w LINQ, które używa lewego sprzężenia zewnętrznego z wieloma warunkami w klauzuli ON.
Posłużę się przykładem następujących dwóch tabel Project (ProjectID, ProjectName) i Task (TaskID, ProjectID, TaskName, Completed). Chcę zobaczyć pełną listę wszystkich projektów z przypisanymi im zadaniami, ale tylko te zadania, które zostały zakończone.
Nie mogę użyć filtru dla, Completed == true
ponieważ spowoduje to odfiltrowanie projektów, które nie mają ukończonych zadań. Zamiast tego chcę dodać Completed == true
klauzulę ON w złączeniu, aby wyświetlić pełną listę projektów, ale zostaną wyświetlone tylko ukończone zadania. W projektach bez ukończonych zadań zostanie wyświetlony pojedynczy wiersz z wartością null dla zadania.
Oto podstawa zapytania.
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 }
Jak dodać && t2.Completed == true
do klauzuli on?
Nie mogę znaleźć żadnej dokumentacji LINQ, jak to zrobić.
Odpowiedzi:
Musisz tylko nazwać anonimową właściwość taką samą po obu stronach
on new { t1.ProjectID, SecondProperty = true } equals new { t2.ProjectID, SecondProperty = t2.Completed } into j1
Opierając się na komentarzach @svick, oto kolejna implementacja, która może mieć większy sens:
from t1 in Projects from t2 in Tasks.Where(x => t1.ProjectID == x.ProjectID && x.Completed == true) .DefaultIfEmpty() select new { t1.ProjectName, t2.TaskName }
źródło
and
, a nie jedna równość jakiegoś „dziwnego” obiektu. Aby udowodnić mój punkt widzenia, twój kod jest błędny. Aby to działało, musiałbyś miećtrue
po lewej it2.Complete
po prawej stronie.AND SecondProperty IN (123, 456)
. Podejmę się tego wyzwania i każda pomoc, której mógłbyś udzielić, byłaby bardzo wdzięczna.Tutaj idziesz z:
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 }
źródło
Nie możesz tego zrobić w ten sposób.
join
Klauzula (aJoin()
metoda rozszerzenie) obsługuje tylko equijoins. To także powód, dlaczego używa,equals
a nie==
. A nawet gdybyś mógł zrobić coś takiego, to nie zadziała, ponieważjoin
jest złączeniem wewnętrznym, a nie złączem zewnętrznym.źródło
Działa to dobrze w przypadku 2 tabel. Mam 3 tabele i na klauzuli muszę połączyć 2 warunki z 3 tabel. Mój kod:
z p w _dbContext.Products dołącz pv w _dbContext.ProductVariants na p.ProduktId równa się pv.ProduktId dołącz jpr w leftJoinQuery na nowym {VariantId = pv.Vid, ProductId = p.ProduktId} równa się nowy {VariantId.Vprices.Vprices. ProductId = jpr.Prices.ProduktID} do lj
Ale w tym momencie pokazuje błąd: dołącz pv w _dbContext.ProductVariants na p.ProduktId równa się pv.ProduktId
Błąd: typ jednego z wyrażeń w klauzuli join jest nieprawidłowy. Wnioskowanie o typie nie powiodło się w wywołaniu „GroupJoin”.
źródło