Wie mache ich einen Join in Linq zu SQL mit Methodensyntax?

193

Ich habe viele Beispiele in LINQ to SQL-Beispielen gesehen, wie ein Join in der Abfragesyntax ausgeführt wird, aber ich frage mich, wie dies mit der Methodensyntax geschehen soll. Wie könnte ich zum Beispiel Folgendes tun?

var result = from sc in enumerableOfSomeClass
             join soc in enumerableOfSomeOtherClass
             on sc.Property1 equals soc.Property2
             select new { SomeClass = sc, SomeOtherClass = soc }

mit einem .Join()? Kann jemand ein anderes einfaches Beispiel veranschaulichen oder liefern?

chobo2
quelle

Antworten:

282
var result = from sc in enumerableOfSomeClass
             join soc in enumerableOfSomeOtherClass
             on sc.Property1 equals soc.Property2
             select new { SomeClass = sc, SomeOtherClass = soc };

Wäre gleichbedeutend mit:

var result = enumerableOfSomeClass
    .Join(enumerableOfSomeOtherClass,
          sc => sc.Property1,
          soc => soc.Property2,
          (sc, soc) => new
                       {
                           SomeClass = sc,
                           SomeOtherClass = soc
                       });

Wie Sie sehen können, ist die Abfragesyntax bei Verknüpfungen normalerweise viel besser lesbar als die Lambda-Syntax.

Justin Niessner
quelle
128

Justin hat die Erweiterung korrekt angezeigt, wenn auf den Join nur ein folgt select. Wenn Sie etwas anderes haben, wird es aufgrund transparenter Bezeichner schwieriger - der Mechanismus, den der C # -Compiler verwendet, um den Umfang beider Hälften des Joins zu verbreiten.

Um Justins Beispiel leicht zu ändern:

var result = from sc in enumerableOfSomeClass
             join soc in enumerableOfSomeOtherClass
             on sc.Property1 equals soc.Property2
             where sc.X + sc.Y == 10
             select new { SomeClass = sc, SomeOtherClass = soc }

würde in so etwas umgewandelt werden:

var result = enumerableOfSomeClass
    .Join(enumerableOfSomeOtherClass,
          sc => sc.Property1,
          soc => soc.Property2,
          (sc, soc) => new { sc, soc })
    .Where(z => z.sc.X + z.sc.Y == 10)
    .Select(z => new { SomeClass = z.sc, SomeOtherClass = z.soc });

Das zhier ist die transparente Kennung - aber weil sie transparent ist, können Sie sie in der ursprünglichen Abfrage nicht sehen :)

Jon Skeet
quelle
5

Um die anderen Antworten hier zu ergänzen, können Sie Folgendes tun, wenn Sie ein neues Objekt eines dritten anderen Typs mit einer where-Klausel (z. B. einer, die nicht Ihr Entity Framework-Objekt ist) erstellen möchten:

public IEnumerable<ThirdNonEntityClass> demoMethod(IEnumerable<int> property1Values)
{
    using(var entityFrameworkObjectContext = new EntityFrameworkObjectContext )
    {
        var result = entityFrameworkObjectContext.SomeClass
            .Join(entityFrameworkObjectContext.SomeOtherClass,
                sc => sc.property1,
                soc => soc.property2,
                (sc, soc) => new {sc, soc})
            .Where(s => propertyValues.Any(pvals => pvals == es.sc.property1)
            .Select(s => new ThirdNonEntityClass 
            {
                dataValue1 = s.sc.dataValueA,
                dataValue2 = s.soc.dataValueB
            })
            .ToList();
    }

    return result;

}    

Achten Sie besonders auf das Zwischenobjekt, das in den Klauseln Where und Select erstellt wird.

Beachten Sie, dass wir hier auch nach verbundenen Objekten suchen, deren Eigenschaft1 mit einer der Objekte in der Eingabeliste übereinstimmt.

Ich weiß, dass dies etwas komplexer ist als das, wonach der ursprüngliche Fragesteller gesucht hat, aber hoffentlich hilft es jemandem.

John Meyer
quelle