Wie man Joins in LINQ für mehrere Felder in einem einzelnen Join durchführt

Ich muss eine LINQ2DataSet-Abfrage, die eine Verknüpfung auf mehr als ein Feld (wie folgt) tun

var result = from x in entity join y in entity2 on x.field1 = y.field1 and x.field2 = y.field2 

Ich habe noch eine geeignete Lösung gefunden (ich kann die zusätzlichen Einschränkungen zu einer Where-Klausel hinzufügen, aber dies ist bei weitem keine geeignete Lösung, oder benutze diese Lösung, aber das setzt ein Equi-Join voraus).

Ist es in LINQ möglich, mehrere Felder in einem einzelnen Join beizutreten?

BEARBEITEN

 var result = from x in entity join y in entity2 on new { x.field1, x.field2 } equals new { y.field1, y.field2 } 

ist die Lösung, auf die ich Bezug nehme, wenn ich oben von einem Gleichungssystem aus gehe.

Weiter EDIT

Um auf die Kritik zu antworten, dass mein ursprüngliches Beispiel ein Equijoin war, erkenne ich an, dass meine derzeitige Anforderung ein Equijoin ist und ich habe bereits die oben erwähnte Lösung verwendet.

Ich versuche jedoch zu verstehen, welche Möglichkeiten und Best Practices ich bei LINQ anwenden kann / sollte. Ich werde bald eine Datumsbereichsabfrage mit einer Tabellen-ID machen müssen und dieses Problem gerade vorwegnehmen. Es sieht so aus, als müsste ich den Datumsbereich in der where-Klausel hinzufügen.

Danke wie immer für alle Vorschläge und Kommentare

Die Lösung mit dem anonymen Typ sollte gut funktionieren. LINQ kann nur equijoins darstellen (sowieso mit Join-Klauseln), und das ist tatsächlich das, was Sie gesagt haben, das Sie sowieso basierend auf Ihrer ursprünglichen Abfrage express möchten.

Wenn Sie die Version mit dem anonymen Typ aus einem bestimmten Grund nicht mögen, sollten Sie diesen Grund erklären.

Wenn Sie etwas anderes als das tun wollen, was Sie ursprünglich verlangt haben, geben Sie bitte ein Beispiel dafür, was Sie wirklich tun möchten.

EDIT: Reagieren auf die Bearbeitung in der Frage: Ja, um eine “Datumsbereich” Join zu tun, müssen Sie stattdessen eine Where-Klausel verwenden. Sie sind semantisch gleichwertig, also ist es nur eine Frage der verfügbaren Optimierungen. Equijoins bieten eine einfache Optimierung (in LINQ to Objects, die LINQ to DataSets enthält), indem Sie eine Suche basierend auf der inneren Sequenz erstellen – denken Sie an eine Hashtabelle vom Schlüssel an eine Sequenz von Einträgen, die diesem Schlüssel entsprechen.

Das mit Datumsbereichen zu tun ist etwas schwieriger. Je nachdem, was genau Sie mit einem “Datumsbereich beitreten” meinen, können Sie vielleicht etwas Ähnliches tun – wenn Sie “Bänder” von Daten (z. B. eines pro Jahr) erstellen möchten, so dass zwei Einträge, die in der dasselbe Jahr (aber nicht am selben Datum) sollte übereinstimmen, dann können Sie es tun, indem Sie nur dieses Band als Schlüssel verwenden. Wenn es komplizierter ist, z. B. eine Seite des Joins einen Bereich bereitstellt und die andere Seite des Joins ein einzelnes Datum liefert, wird die Übereinstimmung mit einem where Klausel (nach einer second from Klausel) besser gehandhabt, wenn sie innerhalb dieses Bereichs liegt ) IMO. Du könntest besonders funky wirken, indem du der einen oder anderen Seite befiehlst, Spiele effizienter zu finden, aber das wäre eine Menge Arbeit – ich würde das nur tun, nachdem ich überprüft habe, ob performance ein Problem ist.

 var result = from x in entity join y in entity2 on new { x.field1, x.field2 } equals new { y.field1, y.field2 } 
 var result = from x in entity1 join y in entity2 on new { X1= x.field1, X2= x.field2 } equals new { X1=y.field1, X2= y.field2 } 

Dies müssen Sie tun, wenn sich die Spaltennamen in zwei Entitäten unterscheiden.

Nur um dies mit einer äquivalenten Methodenkettensyntax zu vervollständigen:

 entity.Join(entity2, x => new {x.Field1, x.Field2}, y => new {y.Field1, y.Field2}, (x, y) => x); 

Während das letzte Argument (x, y) => x ist, was Sie auswählen (im obigen Fall wählen wir x ).

Ich denke, eine besser lesbare und flexible Option ist die Where-function:

 var result = from x in entity1 from y in entity2 .Where(y => y.field1 == x.field1 && y.field2 == x.field2) 

Dies ermöglicht auch einen einfachen Wechsel von innerer Verknüpfung zu linker Verknüpfung durch Anhängen von .DefaultIfEmpty ().

 var result = from x in entity join y in entity2 on new { X1= x.field1, X2= x.field2 } equals new { X1=y.field1, X2= y.field2 } select new { /// Columns }; 

Mit dem Join-Operator können Sie nur Equi-Joins ausführen. Andere Arten von Verknüpfungen können unter Verwendung anderer Operatoren erstellt werden. Ich bin mir nicht sicher, ob der genaue Join, den Sie versuchen, einfacher wäre, wenn Sie diese Methoden verwenden oder die where-Klausel ändern. Dokumentation zur Join-Klausel finden Sie hier . MSDN enthält einen Artikel zu Join-Vorgängen mit mehreren Links zu Beispielen anderer Joins.

Du könntest etwas wie (unten) tun

 var query = from p in context.T1 join q in context.T2 on new { p.Col1, p.Col2 } equals new { q.Col1, q.Col2 } select new {p...., q......}; 

Wenn der Feldname in Entitäten unterschiedlich ist

 var result = from x in entity join y in entity2 on new { field1= x.field1, field2 = x.field2 } equals new { field1= y.field1, field2= y.myfield } select new {x,y}); 

Deklarieren Sie eine class (Typ), um die Elemente beizubehalten, denen Sie beitreten möchten. Im folgenden Beispiel deklariere JoinElement

  public class **JoinElement** { public int? Id { get; set; } public string Name { get; set; } } results = from course in courseQueryable.AsQueryable() join agency in agencyQueryable.AsQueryable() on new **JoinElement**() { Id = course.CourseAgencyId, Name = course.CourseDeveloper } equals new **JoinElement**() { Id = agency.CourseAgencyId, Name = "D" } into temp1 

Als eine vollständige Methodenkette, die wie folgt aussehen würde:

 lista.SelectMany(a => listb.Where(xi => b.Id == a.Id && b.Total != a.Total), (a, b) => new ResultItem { Id = a.Id, ATotal = a.Total, BTotal = b.Total }).ToList(); 
 from d in db.CourseDispatches join du in db.DispatchUsers on d.id equals du.dispatch_id join u in db.Users on du.user_id equals u.id join fr in db.Forumreports on (d.course_id + '_' + du.user_id) equals (fr.course_id + '_'+ fr.uid) 

Das funktioniert für mich