Jak wykonać lewe połączenie zewnętrzne w C # LINQ do obiektów bez użycia join-on-equals-into
klauzul? Czy można to zrobić za pomocą where
klauzuli? Prawidłowy problem: łączenie wewnętrzne jest łatwe i mam takie rozwiązanie
List<JoinPair> innerFinal = (from l in lefts from r in rights where l.Key == r.Key
select new JoinPair { LeftId = l.Id, RightId = r.Id})
ale dla lewego złączenia zewnętrznego potrzebuję rozwiązania. Mój jest coś takiego, ale nie działa
List< JoinPair> leftFinal = (from l in lefts from r in rights
select new JoinPair {
LeftId = l.Id,
RightId = ((l.Key==r.Key) ? r.Id : 0
})
gdzie JoinPair jest klasą:
public class JoinPair { long leftId; long rightId; }
Odpowiedzi:
Jak stwierdzono w:
101 próbek LINQ - lewe połączenie zewnętrzne
źródło
Jeśli używany jest dostawca LINQ oparty na bazie danych, można znacznie lepiej odczytać lewe łączenie zewnętrzne:
Jeśli pominiesz to
DefaultIfEmpty()
, będziesz mieć wewnętrzne połączenie.Weź przyjętą odpowiedź:
Ta składnia jest bardzo myląca i nie jest jasne, jak to działa, gdy chcesz opuścić dołączanie do WIELU tabel.
Uwaga
Należy zauważyć, że
from alias in Repo.whatever.Where(condition).DefaultIfEmpty()
jest to to samo, co zewnętrzny-zastosuj / lewy-złącz-boczny, który dowolny (porządny) optymalizator bazy danych jest w stanie doskonale przetłumaczyć na lewe złączenie, o ile nie wprowadzisz poszczególnych wierszy -wartości (inaczej rzeczywiste zastosowanie zewnętrzne). Nie rób tego w Linq-2-Objects (ponieważ nie ma optymalizatora DB, gdy używasz Linq-to-Objects).Szczegółowy przykład
W połączeniu z LINQ 2 SQL ładnie przełoży się na następujące bardzo czytelne zapytanie SQL:
Edytować:
Zobacz także „ Konwertuj zapytanie SQL Server na zapytanie Linq ”, aby uzyskać bardziej złożony przykład.
Ponadto, jeśli robisz to w Linq-2-Objects (zamiast Linq-2-SQL), powinieneś to zrobić w staromodny sposób (ponieważ LINQ na SQL tłumaczy to poprawnie, aby połączyć operacje, ale nad obiektami ta metoda wymusza pełne skanowanie i nie korzysta z wyszukiwania indeksów, cokolwiek ...):
źródło
join
where
DefaultIfEmpty
Korzystanie z wyrażenia lambda
źródło
Enumerable.Empty<Product>.DefaultIfEmpty()
że zwróci IEnumerable z pojedynczą wartościądefault(Product)
.Teraz jako metoda rozszerzenia:
Używaj tak, jak normalnie używasz łączenia:
Mam nadzieję, że to pozwoli Ci zaoszczędzić trochę czasu.
źródło
Spójrz na ten przykład . To zapytanie powinno działać:
źródło
r
można uzyskać dostęp w klauzuli select po użyciu przyłączenia do?r
w drugiejfrom
klauzuli. tzn. wfrom r in lrs.DefaultIfEmpty()
przeciwnym razie to zapytanie nie ma większego sensu i prawdopodobnie nawet się nie kompiluje z powodur
braku kontekstu dla zaznaczenia.Clockwise
z Johnem Cleese, lol.Może wyglądać implementacja lewego łączenia zewnętrznego metodami rozszerzenia
Następnie wynikowy selektor musi zająć się zerowymi elementami. Fx.
źródło
spójrz na ten przykład
teraz możesz,
include elements from the left
nawet jeśli ten elementhas no matches in the right
, w naszym przypadku wycofaliśmyArlene
nawet on nie ma pasującego odpowiednikatutaj jest odniesienie
Instrukcje: wykonywanie lewych połączeń zewnętrznych (przewodnik programowania w języku C #)
źródło
To jest forma ogólna (jak już podano w innych odpowiedziach)
Oto wyjaśnienie, które mam nadzieję wyjaśni, co to właściwie oznacza!
zasadniczo tworzy osobny zestaw wyników b_temp, który skutecznie zawiera null „wiersze” dla wpisów po prawej stronie (wpisy w „b”).
Następnie następny wiersz:
.. powtarza ten zestaw wyników, ustawiając domyślną wartość zerową dla „wiersza” po prawej stronie i ustawiając wynik łączenia wiersza po prawej stronie na wartość „b_value” (tj. wartość znajdującą się po prawej stronie strona strony, jeśli istnieje pasujący rekord lub „null”, jeśli nie ma).
Teraz, jeśli prawa strona jest wynikiem oddzielnego zapytania LINQ, będzie się składać z anonimowych typów, które mogą być albo „czymś”, albo „zerą”. Jeśli jednak jest to wyliczenie (np. Lista - gdzie MyObjectB jest klasą z 2 polami), można sprecyzować, jakie domyślne wartości „null” są używane dla jego właściwości:
Zapewnia to, że samo „b” nie ma wartości NULL (ale jego właściwości mogą być zerowe, przy użyciu domyślnych wartości NULL, które określiłeś), a to pozwala ci sprawdzać właściwości wartości b_value bez uzyskania wyjątku odniesienia NULL dla b_value. Należy zauważyć, że w przypadku zerowej wartości DateTime typ (DateTime?), Tj. „Zerowy DateTime”, musi być określony jako „Typ” wartości null w specyfikacji dla „DefaultIfEmpty” (będzie to również dotyczyło typów, które nie są „natywnie” nullable np. double, float).
Możesz wykonać wiele lewych złączeń zewnętrznych, po prostu łącząc powyższą składnię.
źródło
Oto przykład, jeśli chcesz dołączyć do więcej niż 2 tabel:
Patrz: https://stackoverflow.com/a/17142392/2343
źródło
Metoda rozszerzenia, która działa jak lewy łączenie ze składnią Join
właśnie napisałem to w .NET core i wydaje się, że działa zgodnie z oczekiwaniami.
Mały test:
źródło
Oto dość łatwa do zrozumienia wersja wykorzystująca składnię metody:
źródło
Istnieją trzy tabele: osoby, szkoły i osoby_szkolne, które łączą osoby ze szkołami, w których studiują. Odwołanie do osoby o id = 6 jest nieobecne w tabeli osoby_szkolne. Jednak osoba o id = 6 jest prezentowana w wyniku siatki połączonej w lewo.
źródło
Jest to składnia SQL w porównaniu do składni LINQ dla złączeń wewnętrznych i lewych zewnętrznych. Lewy zewnętrzny łącznik:
http://www.ozkary.com/2011/07/linq-to-entity-inner-and-left-joins.html
„W poniższym przykładzie łączenie grupy między produktem i kategorią. Jest to zasadniczo lewe łączenie. Wyrażenie wyrażenia zwraca dane, nawet jeśli tabela kategorii jest pusta. Aby uzyskać dostęp do właściwości tabeli kategorii, musimy teraz wybrać z wyliczalnego wyniku przez dodanie instrukcji from cl w catList.DefaultIfEmpty ().
źródło
Wykonaj lewe połączenia zewnętrzne w linq C # // Wykonaj lewe połączenia zewnętrzne
https://dotnetwithhamid.blogspot.in/
źródło
Chciałbym dodać, że jeśli dostaniesz rozszerzenie MoreLinq, teraz jest teraz obsługiwane zarówno homogeniczne, jak i heterogeniczne lewe połączenia.
http://morelinq.github.io/2.8/ref/api/html/Overload_MoreLinq_MoreEnumerable_LeftJoin.htm
przykład:
EDYTOWAĆ:
Z perspektywy czasu może to działać, ale konwertuje IQueryable na IEnumerable, ponieważ morelinq nie konwertuje zapytania na SQL.
Zamiast tego możesz użyć GroupJoin, jak opisano tutaj: https://stackoverflow.com/a/24273804/4251433
Zapewni to, że pozostanie jako IQueryable na wypadek, gdybyś musiał później wykonać dalsze operacje logiczne.
źródło
Prostym sposobem jest użycie słowa kluczowego Let. To działa dla mnie.
To symulacja Left Join. Jeśli każdy element w tabeli B nie pasuje do elementu A, BItem zwraca wartość null
źródło
Jeśli chcesz dołączyć i przefiltrować coś, możesz to zrobić poza łączeniem. Filtr można wykonać po utworzeniu kolekcji.
W takim przypadku, jeśli zrobię to w stanie łączenia, zmniejszę liczbę zwracanych wierszy.
Stosowany jest warunek trójskładnikowy
(= n == null ? "__" : n.MonDayNote,)
Jeśli obiekt jest
null
(więc nie pasuje), to zwróć to, co następuje po?
.__
, w tym przypadku.Innego, co jest wrócić po
:
,n.MonDayNote
.Dzięki innym autorom, od tego momentu zacząłem od własnego problemu.
źródło
WYNIK
źródło
Zgodnie z moją odpowiedzią na podobne pytanie tutaj:
Lewe łączenie zewnętrzne Linq-SQL za pomocą składni Lambda i łączenie na 2 kolumnach (kompozytowy klucz łączenia)
Pobierz kod tutaj lub sklonuj moje repozytorium github i graj!
Pytanie:
Lambda:
źródło
Omówienie: W tym fragmencie kodu pokazuję, jak grupować według identyfikatora, gdzie Tabela 1 i Tabela 2 mają relację jeden do wielu. Grupuję według Id, Field1 i Field2. Podkwerenda jest pomocna, jeśli wymagane jest trzecie wyszukiwanie w Tabeli i wymagałoby relacji łączenia po lewej stronie. Pokazuję lewe grupowanie dołączania i podzapytanie linq. Wyniki są równoważne.
źródło
źródło
Proste rozwiązanie dla LEFT OUTER JOIN :
uwagi :
źródło
setA
isetB
odpowiedź.