Wenn ein datenbankgesteuerter LINQ-Anbieter verwendet wird, kann ein wesentlich besser lesbarer linker Outer Join als solcher geschrieben werden:
from maintable in Repo.T_Whatever
from xxx in Repo.T_ANY_TABLE.Where(join condition).DefaultIfEmpty()
Wenn Sie das weglassen 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 Sie MULTIPLE-Tabellen links verknüpfen möchten.
Hinweis
Es sollte beachtet werden, dass dies from alias in Repo.whatever.Where(condition).DefaultIfEmpty()
dasselbe ist wie ein Outer-Apply / Left-Join-Lateral, das jeder (anständige) Datenbankoptimierer perfekt in einen Left-Join übersetzen kann, solange Sie nicht pro Zeile einführen -Werte (auch bekannt als tatsächliche äußere Anwendung). Tun Sie dies nicht in Linq-2-Objects (da es keinen DB-Optimierer gibt, wenn Sie Linq-to-Objects verwenden).
Detailliertes 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 mit LINQ 2 SQL lässt sich dies gut in die folgende gut lesbare SQL-Abfrage übersetzen:
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
Bearbeiten:
Ein komplexeres Beispiel finden Sie unter "
Konvertieren der SQL Server-Abfrage in eine Linq-Abfrage ".
Wenn Sie dies in Linq-2-Objects (anstelle von Linq-2-SQL) tun, sollten Sie dies auf die altmodische Weise tun (da LINQ to SQL dies korrekt übersetzt, um Operationen zu verbinden, jedoch über Objekte dieser Methode erzwingt einen vollständigen Scan und nutzt die Indexsuche nicht aus, 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
}
);