Jak wykonać łączenie w linq do sql ze składnią metody?

193

Widziałem wiele przykładów w LINQ do SQL przykładów, jak wykonać łączenie w składni zapytania, ale zastanawiam się, jak to zrobić ze składnią metody? Na przykład, jak mogę wykonać następujące czynności

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

z .Join()? Czy ktoś może zilustrować lub podać inny prosty przykład?

chobo2
źródło

Odpowiedzi:

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

Byłby równoważny z:

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

Jak widać, jeśli chodzi o sprzężenia, składnia zapytań jest zwykle znacznie bardziej czytelna niż składnia lambda.

Justin Niessner
źródło
129

Justin poprawnie pokazał rozwinięcie w przypadku, gdy po dołączeniu następuje po prostu znak select. Jeśli masz coś innego, staje się to trudniejsze ze względu na przejrzyste identyfikatory - mechanizm, którego używa kompilator C # do propagowania zakresu obu połówek złączenia.

Aby nieco zmienić przykład Justina:

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 }

zostanie przekształcony w coś takiego:

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 });

zTutaj jest przezroczysty identyfikator - ale dlatego, że jest przezroczysta, nie można zobaczyć go w oryginalnym zapytaniu :)

Jon Skeet
źródło
5

Aby dodać do innych odpowiedzi tutaj, jeśli chcesz utworzyć nowy obiekt trzeciego innego typu z klauzulą ​​where (np. Taki, który nie jest twoim obiektem Entity Framework), możesz to zrobić:

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;

}    

Zwróć szczególną uwagę na obiekt pośredni, który jest tworzony w klauzulach Where i Select.

Zauważ, że tutaj szukamy również wszelkich połączonych obiektów, które mają właściwość1, która pasuje do jednego z tych na liście danych wejściowych.

Wiem, że jest to nieco bardziej skomplikowane niż to, czego szukał pierwotny pytający, ale mam nadzieję, że to komuś pomoże.

John Meyer
źródło