Zakładając, że mam lewe połączenie zewnętrzne jako takie:
from f in Foo
join b in Bar on f.Foo_Id equals b.Foo_Id into g
from result in g.DefaultIfEmpty()
select new { Foo = f, Bar = result }
Jak wyraziłbym to samo zadanie za pomocą metod rozszerzenia? Na przykład
Foo.GroupJoin(Bar, f => f.Foo_Id, b => b.Foo_Id, (f,b) => ???)
.Select(???)
c#
linq-to-sql
lambda
LaserJesus
źródło
źródło
GroupJoin
robi lewe połączenie zewnętrzne,SelectMany
część jest potrzebna tylko w zależności od tego, co chcesz wybrać.Ponieważ wydaje się, że jest to de facto pytanie SO dla lewych złączeń zewnętrznych przy użyciu składni metody (rozszerzenia), pomyślałem, że dodam alternatywę do obecnie wybranej odpowiedzi, która (przynajmniej z mojego doświadczenia) była częściej tym, czym jestem po
Aby wyświetlić różnicę za pomocą prostego zestawu danych (zakładając, że łączymy się na samych wartościach):
Opcja 2 jest zgodna z typową lewą definicją łączenia zewnętrznego, ale jak wspomniałem wcześniej, jest często niepotrzebnie złożona w zależności od zestawu danych.
źródło
Single
sprawdzenia pośrodku łączenia.SingleOrDefault
jest jednak bardziej „poprawnym” sposobem wykazania tego IMO.Metoda łączenia grupowego nie jest konieczna do uzyskania połączenia dwóch zestawów danych.
Przyłączenie wewnętrzne:
Dla Left Join wystarczy dodać DefaultIfEmpty ()
EF i LINQ na SQL poprawnie przekształcają się w SQL. W przypadku LINQ to Objects lepiej dołączyć przy użyciu GroupJoin, ponieważ wewnętrznie korzysta z wyszukiwania . Ale jeśli pytasz DB, pomijanie GroupJoin jest AFAIK jako wydajne.
Personlay dla mnie w ten sposób jest bardziej czytelny w porównaniu do GroupJoin ().
źródło
Możesz utworzyć metodę rozszerzenia, taką jak:
źródło
Poprawiając odpowiedź Ocelot20, jeśli masz stolik, na którym chcesz się połączyć zewnętrznie, z którego chcesz tylko 0 lub 1 wierszy, ale może on mieć wiele, musisz zamówić połączoną tabelę:
W przeciwnym razie wiersz, który otrzymasz w złączeniu, będzie losowy (a ściślej, w zależności od tego, co db znajdzie najpierw).
źródło
Zmieniając odpowiedź Marca Gravella w metodę rozszerzenia, zrobiłem następujące.
źródło
Chociaż zaakceptowana odpowiedź działa i jest dobra dla Linq na obiekty, wkurzyło mnie to, że zapytanie SQL nie jest zwykłym lewym zewnętrznym złączeniem.
Poniższy kod opiera się na projekcie LinkKit, który umożliwia przekazywanie wyrażeń i wywoływanie ich w zapytaniu.
Można go używać w następujący sposób
źródło
Jest na to łatwe rozwiązanie
Wystarczy użyć .HasValue w swoim Select
Bardzo łatwe, nie wymaga dołączania do grupy ani niczego innego
źródło