Wenn ein datenbankgestützter LINQ-Anbieter verwendet wird, kann eine wesentlich lesbarere linke äußere Verknüpfung als solche geschrieben werden:
from maintable in Repo.T_Whatever
from xxx in Repo.T_ANY_TABLE.Where(join condition).DefaultIfEmpty()
Wenn Sie die DefaultIfEmpty()
haben Sie eine innere Verbindung.
Nehmen Sie die akzeptierte Antwort:
from c in categories
join p in products on c equals p.Category into ps
from p in ps.DefaultIfEmpty()
Diese Syntax ist sehr verwirrend, und es ist nicht klar, wie sie funktioniert, wenn man MEHRERE Tabellen links verknüpfen will.
Hinweis
Es ist zu beachten, dass from alias in Repo.whatever.Where(condition).DefaultIfEmpty()
ist dasselbe wie ein outer-apply/left-join-lateral, das jeder (anständige) Datenbank-Optimierer perfekt in einen left-join übersetzen kann, solange Sie keine per-row-Werte einführen (aka ein tatsächliches outer apply). Tun Sie dies nicht in Linq-2-Objects (denn es gibt keine DB-Optimierer, wenn Sie Linq-to-Objects verwenden).
Ausführliches Beispiel
var query2 = (
from users in Repo.T_User
from mappings in Repo.T_User_Group
.Where(mapping => mapping.USRGRP_USR == users.USR_ID)
.DefaultIfEmpty() // <== makes join left join
from groups in Repo.T_Group
.Where(gruppe => gruppe.GRP_ID == mappings.USRGRP_GRP)
.DefaultIfEmpty() // <== makes join left join
// where users.USR_Name.Contains(keyword)
// || mappings.USRGRP_USR.Equals(666)
// || mappings.USRGRP_USR == 666
// || groups.Name.Contains(keyword)
select new
{
UserId = users.USR_ID
,UserName = users.USR_User
,UserGroupId = groups.ID
,GroupName = groups.Name
}
);
var xy = (query2).ToList();
Bei Verwendung von LINQ 2 SQL lässt sich die folgende sehr gut lesbare SQL-Abfrage erstellen:
SELECT
users.USR_ID AS UserId
,users.USR_User AS UserName
,groups.ID AS UserGroupId
,groups.Name AS GroupName
FROM T_User AS users
LEFT JOIN T_User_Group AS mappings
ON mappings.USRGRP_USR = users.USR_ID
LEFT JOIN T_Group AS groups
ON groups.GRP_ID == mappings.USRGRP_GRP
Editar:
Siehe auch " SQL Server-Abfrage in Linq-Abfrage konvertieren " für ein komplexeres Beispiel.
Auch, wenn Sie es in Linq-2-Objekte (anstelle von Linq-2-SQL) tun, sollten Sie es die altmodische Art und Weise tun (weil LINQ to SQL dies korrekt auf Join-Operationen übersetzt, aber über Objekte erzwingt diese Methode einen vollständigen Scan, und nutzt nicht die Vorteile der Indexsuche, warum auch immer...):
var query2 = (
from users in Repo.T_Benutzer
join mappings in Repo.T_Benutzer_Benutzergruppen on mappings.BEBG_BE equals users.BE_ID into tmpMapp
join groups in Repo.T_Benutzergruppen on groups.ID equals mappings.BEBG_BG into tmpGroups
from mappings in tmpMapp.DefaultIfEmpty()
from groups in tmpGroups.DefaultIfEmpty()
select new
{
UserId = users.BE_ID
,UserName = users.BE_User
,UserGroupId = mappings.BEBG_BG
,GroupName = groups.Name
}
);
3 Stimmen
Können Sie ein Beispiel dafür geben, was Sie zu erreichen versuchen?
0 Stimmen
Normale linke äußere Verknüpfung ist so etwas wie dieses: var a = from b in bb join c in cc on b.bbbbb equals c.ccccc into dd from d in dd.DefaultIfEmpty() select b.sss; Meine Frage ist es eine Möglichkeit zu tun, dass ohne Verwendung von join-on-equals-into-Klauseln etwas wie dieses var a = from b in bb from c in cc where b.bbb == c.cccc ... und so weiter...
2 Stimmen
Sicher gibt es, aber Sie sollten ein Beispiel für Ihren Code posten, den Sie bereits haben, damit die Leute Ihnen eine bessere Antwort geben können
1 Stimmen
Ich suchte nach einem "Links ohne " JOIN (und ich habe es mit dem Begriff "OUTER" verwechselt). Diese Antwort entsprach eher dem, was ich wollte.
0 Stimmen
Ähnlicher Beitrag - Linq join iquery, wie man defaultifempty verwendet
0 Stimmen
Siehe auch Linq to Entities join vs. groupjoin .
0 Stimmen
Für Linq-to-Entities (nicht Objects), siehe diese Frage: stackoverflow.com/questions/19356439/