Справка по пониманию Enumerable.Join Method

Вчера я разместил этот вопрос относительно использования lambdas внутри метода Join(), чтобы проверить, существует ли 2 условия для двух объектов. Я получил ответ на вопрос, который работал отлично. Я подумал, прочитав статью MSDN по методу Enumerable.Join(), я бы точно понял, что происходит, но я этого не делаю. Может ли кто-нибудь помочь мне понять, что происходит в приведенном ниже коде (метод Join())? Спасибо заранее.

if (db.TableA.Where( a => a.UserID == currentUser )
      .Join( db.TableB.Where( b => b.MyField == someValue ),
             o => o.someFieldID,
             i => i.someFieldID,
             (o,i) => o )
      .Any()) 
{
    //...
}

Изменить: В частности, мне интересно узнать о последних трех параметрах и о том, что происходит на самом деле. Как они приводят к требованиям подписи Func (TOuter, TKey), Func (TInner, TKey) и т.д.

Ответ 1

Эрик и Ник дали хорошие ответы.

Вы также можете написать выражение запроса Linq, используя синтаксис запроса (синтаксис синтаксиса, который вы используете в своем примере):

var query = from a in db.TableA 
            join b in db.TableB on a.someFieldID equals b.someFieldID
            where a.UserID == currentUser && b.MyField == someValue
            select a;

        if (query.Any()) {
            ...
        }

Update:

Вы, кажется, застряли на лямбда-выражениях. Это функция, которую вы проходите как переменная. Выражение лямбда эквивалентно анонимному делегату (или анонимному методу, для меня более общим).

Вот ваш запрос с лямбда-выражениями в качестве делегатов (замените EntityType на тип вашего объекта, возвращенный из TableA, конечно):

if (db.TableA.Where( delegate(EntityType a) { return a.UserID == currentUser; } ) 
  .Join( db.TableB.Where( delegate(EntityType b) { return b.MyField == someValue; } ), 
         delegate(EntityType o) { return o.somefieldId); },
         delegate(EntityType i) { return i.someFieldId); },
         delegate(EntityType o, EntityType i) { return o; }) 
  .Any())  

{   //... }

ПРИМЕЧАНИЕ. Выражение лямбда имеет важные аспекты, которые делают его более чем эквивалентным для анонимных методов. Я рекомендую вам просмотреть другие вопросы SO и прочитать онлайн о лямбда-выражениях в частности. Они позволяют выражать очень сильные идеи в гораздо более простом и элегантном стиле. Это глубокая тема, но основы достаточно легки для понимания. Это функция, которую вы можете передавать как переменную, или как параметр для других функций.

Ответ 2

Синтаксис соединения

FirstTable.Join(SecondTable, FirstTableKeyExtractor, SecondTableKeyExtractor, Selector)

Итак, у вас есть две таблицы. У вас есть ключ, который является общим для обеих таблиц. Вы предоставляете два ключевых экстрактора, которые знают, как получить ключ из каждой строки в таблице.

Логика объединения идентифицирует пары строк, по одному из каждой таблицы, которые имеют один и тот же ключ.

Каждая из этих строк затем запускается через селектор, чтобы спроецировать результат.

Отвечает ли это на ваш вопрос?

Ответ 3

Объяснение соединения.

b= тип объекта первой таблицы o= тип объекта первой таблицы i= тип объекта второй таблицы

  • db.TableB.Where( b => b.MyField == someValue ) Это тип элемента второй таблицы
  • o => o.someFieldID Ключ первой таблицы
  • i => i.someFieldID Ключ второй таблицы (который будет соответствовать ключу в первой таблице)
  • (o,i) => o Объект, возвращающий в этом случае тип объекта первой таблицы.

Ответ 4

Этот запрос говорит join TableA to TableB где TableA.someFieldID == TableB.someFieldID и выбирая результаты из таблицы A и видя, есть ли какие-либо результаты вообще

С точки зрения SQL, подумайте об этом так, даже если это не Linq-to-SQL... если вы знакомы с SQL, возможно, это имеет смысл:

Select Count(*)
From TableA a
     Join TableB b
       On a.someFieldID = b.someFieldID

Затем, если проверка Count(*) равнa > 0