Ich probiere LINQ für Entitäten aus.
Ich habe ein Problem mit Folgendem: Ich möchte, dass es dies tut:
SELECT
T_Benutzer.BE_User
,T_Benutzer_Benutzergruppen.BEBG_BE
FROM T_Benutzer
LEFT JOIN T_Benutzer_Benutzergruppen
ON T_Benutzer_Benutzergruppen.BEBG_BE = T_Benutzer.BE_ID
Das nächste, zu dem ich gekommen bin, ist Folgendes:
var lol = (
from u in Repo.T_Benutzer
//where u.BE_ID == 1
from o in Repo.T_Benutzer_Benutzergruppen.DefaultIfEmpty()
// on u.BE_ID equals o.BEBG_BE
where (u.BE_ID == o.BEBG_BE || o.BEBG_BE == null)
//join bg in Repo.T_Benutzergruppen.DefaultIfEmpty()
// on o.BEBG_BG equals bg.ID
//where bg.ID == 899
orderby
u.BE_Name ascending
//, bg.Name descending
//select u
select new
{
u.BE_User
,o.BEBG_BG
//, bg.Name
}
).ToList();
Dies führt jedoch zu denselben Ergebnissen wie eine innere Verknüpfung und nicht zu einer linken Verknüpfung.
Darüber hinaus erstellt es diese völlig verrückte SQL:
SELECT
[Extent1].[BE_ID] AS [BE_ID]
,[Extent1].[BE_User] AS [BE_User]
,[Join1].[BEBG_BG] AS [BEBG_BG]
FROM [dbo].[T_Benutzer] AS [Extent1]
CROSS JOIN
(
SELECT
[Extent2].[BEBG_BE] AS [BEBG_BE]
,[Extent2].[BEBG_BG] AS [BEBG_BG]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
LEFT OUTER JOIN [dbo].[T_Benutzer_Benutzergruppen] AS [Extent2]
ON 1 = 1
) AS [Join1]
WHERE [Extent1].[BE_ID] = [Join1].[BEBG_BE]
OR [Join1].[BEBG_BE] IS NULL
ORDER BY [Extent1].[BE_Name] ASC
Wie kann ich eine Linksverknüpfung in LINQ-2-Entitäten so durchführen, dass eine andere Person noch verstehen kann, was in diesem Code getan wird?
und am meisten bevorzugt, wo das generierte SQL aussieht:
SELECT
T_Benutzer.BE_User
,T_Benutzer_Benutzergruppen.BEBG_BE
FROM T_Benutzer
LEFT JOIN T_Benutzer_Benutzergruppen
ON T_Benutzer_Benutzergruppen.BEBG_BE = T_Benutzer.BE_ID
c#
linq
entity-framework
entity-framework-4
linq-to-entities
Stefan Steiger
quelle
quelle
Antworten:
Ah, ich habe es selbst.
Die Macken und Quarks von LINQ-2-Entitäten.
Das sieht am verständlichsten aus:
var query2 = ( from users in Repo.T_Benutzer from mappings in Repo.T_Benutzer_Benutzergruppen .Where(mapping => mapping.BEBG_BE == users.BE_ID).DefaultIfEmpty() from groups in Repo.T_Benutzergruppen .Where(gruppe => gruppe.ID == mappings.BEBG_BG).DefaultIfEmpty() //where users.BE_Name.Contains(keyword) // //|| mappings.BEBG_BE.Equals(666) //|| mappings.BEBG_BE == 666 //|| groups.Name.Contains(keyword) select new { UserId = users.BE_ID ,UserName = users.BE_User ,UserGroupId = mappings.BEBG_BG ,GroupName = groups.Name } ); var xy = (query2).ToList();
Entfernen Sie die
.DefaultIfEmpty()
, und Sie erhalten eine innere Verbindung.Das war es, wonach ich gesucht habe.
quelle
Hier können Sie einen Artikel lesen, den ich für Joins in LINQ geschrieben habe
var query = from u in Repo.T_Benutzer join bg in Repo.T_Benutzer_Benutzergruppen on u.BE_ID equals bg.BEBG_BE into temp from j in temp.DefaultIfEmpty() select new { BE_User = u.BE_User, BEBG_BG = (int?)j.BEBG_BG// == null ? -1 : j.BEBG_BG //, bg.Name }
Das Folgende entspricht den Erweiterungsmethoden:
var query = Repo.T_Benutzer .GroupJoin ( Repo.T_Benutzer_Benutzergruppen, x=>x.BE_ID, x=>x.BEBG_BE, (o,i)=>new {o,i} ) .SelectMany ( x => x.i.DefaultIfEmpty(), (o,i) => new { BE_User = o.o.BE_User, BEBG_BG = (int?)i.BEBG_BG } );
quelle
GroupJoin
undSelectMany
Paare immer wieder wiederholen , können Sie eine schöne, wenn auch lange Lösung haben :)Vielleicht komme ich später, um zu antworten, aber jetzt stehe ich vor dieser Frage ... Wenn es hilft, gibt es noch eine Lösung (so wie ich sie gelöst habe).
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 } );
Übrigens habe ich versucht, den Stefan Steiger-Code zu verwenden, der auch hilft, aber er war höllisch langsamer.
quelle
Der einfache Weg ist die Verwendung des Schlüsselworts Let. Das funktioniert bei mir.
from AItem in Db.A Let BItem = Db.B.Where(x => x.id == AItem.id ).FirstOrDefault() Where SomeCondition Select new YourViewModel { X1 = AItem.a, X2 = AItem.b, X3 = BItem.c }
Dies ist eine Simulation von Left Join. Wenn nicht jedes Element in der Tabelle B mit dem Element A übereinstimmt, gibt BItem null zurück
quelle
Sie können dies nicht nur in Entitäten verwenden, sondern auch Prozeduren oder andere Datenquellen speichern:
var customer = (from cus in _billingCommonservice.BillingUnit.CustomerRepository.GetAll() join man in _billingCommonservice.BillingUnit.FunctionRepository.ManagersCustomerValue() on cus.CustomerID equals man.CustomerID // start left join into a from b in a.DefaultIfEmpty(new DJBL_uspGetAllManagerCustomer_Result() ) select new { cus.MobileNo1,b.ActiveStatus });
quelle