Как сделать объединение в linq к sql с синтаксисом метода?

193

Я видел много примеров в LINQ to SQL о том, как сделать объединение в синтаксисе запроса, но мне интересно, как это сделать с помощью синтаксиса метода? Например, как я могу сделать следующее

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

с .Join()? Кто-нибудь может проиллюстрировать или привести еще один простой пример?

chobo2
источник

Ответы:

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

Будет эквивалентно:

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

Как вы можете видеть, когда дело доходит до объединений, синтаксис запроса обычно гораздо более читабелен, чем лямбда-синтаксис.

Джастин Нисснер
источник
129

Джастин правильно показал расширение в случае, когда за соединением просто следует символ select. Если у вас есть что-то еще, это становится более сложным из-за прозрачных идентификаторов - механизма, который компилятор C # использует для распространения области действия обеих половин объединения.

Таким образом, чтобы немного изменить пример Джастина:

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 }

будет преобразован во что-то вроде этого:

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

zЗдесь прозрачный идентификатор - но потому , что он прозрачен, вы не можете увидеть его в исходном запросе :)

Джон Скит
источник
5

Чтобы добавить сюда другие ответы, если вы хотите создать новый объект третьего отличного типа с предложением where (например, тот, который не является вашим объектом Entity Framework), вы можете сделать это:

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;

}    

Обратите особое внимание на промежуточный объект, который создается в предложениях Where и Select.

Обратите внимание, что здесь мы также ищем любые присоединенные объекты, которые имеют свойство1, совпадающее с одним из объектов в списке ввода.

Я знаю, что это немного сложнее, чем искал первоначальный аскер, но, надеюсь, это кому-нибудь поможет.

Джон Мейер
источник