Si un fournisseur LINQ piloté par une base de données est utilisé, une jointure externe gauche beaucoup plus lisible peut être écrite comme telle:
from maintable in Repo.T_Whatever
from xxx in Repo.T_ANY_TABLE.Where(join condition).DefaultIfEmpty()
Si vous omettez le, DefaultIfEmpty()
vous aurez une jointure interne.
Prenez la réponse acceptée:
from c in categories
join p in products on c equals p.Category into ps
from p in ps.DefaultIfEmpty()
Cette syntaxe est très déroutante, et il n'est pas clair comment cela fonctionne lorsque vous souhaitez quitter les tables MULTIPLE.
Remarque
Il convient de noter que from alias in Repo.whatever.Where(condition).DefaultIfEmpty()
c'est la même chose qu'une application externe / jointure latérale gauche, que tout optimiseur de base de données (décent) est parfaitement capable de traduire en jointure gauche, tant que vous n'introduisez pas de ligne par ligne. -valeurs (alias une application externe réelle). Ne faites pas cela dans Linq-2-Objects (car il n'y a pas d'optimiseur de base de données lorsque vous utilisez Linq-to-Objects).
Exemple détaillé
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();
Lorsqu'il est utilisé avec LINQ 2 SQL, il se traduira parfaitement par la requête SQL très lisible suivante:
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
Éditer:
Voir aussi "
Convertir une requête SQL Server en requête Linq » pour un exemple plus complexe.
De plus, si vous le faites dans Linq-2-Objects (au lieu de Linq-2-SQL), vous devez le faire à l'ancienne (car LINQ to SQL le traduit correctement pour joindre des opérations, mais sur des objets, cette méthode force une analyse complète, et ne tire pas parti des recherches d'index, peu importe ...):
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
}
);