Simple.Data ORM. Идентификатор с несколькими частями не может быть связан

Я использую Simple.Data ORM. Я пытаюсь сделать запрос из двух соединенных таблиц. Этот запрос работает нормально:

dynamic alias;
var candidatesRec = db.dbo.Candidates
            .FindAll(db.dbo.Candidates.CommonOfferId == commonOfferId 
                        && db.dbo.CandidateProfiles.CandidateId == null)
            .LeftJoin(db.dbo.CandidateProfiles, out alias)
            .On(db.dbo.Candidates.Id == alias.CandidateId)
            .Select(
                db.dbo.Candidates.Id,
                db.dbo.Candidates.Email
            )
            .OrderByDescending(db.dbo.Candidates.ApplicationDate)

Но когда добавляется эта строка:

.Skip((pageNumber - 1) * pageSize)

Я получаю это исключение:

Идентификатор с несколькими частями \ "dbo.CandidateProfiles.CandidateId \" может не связаны.

Я пытался явно пропускать 0, 1 и несколько других чисел для пропусков, но всегда получаю то же исключение.

Мой тестовый запрос должен возвращать 4 элемента, и я пропускаю 0 элементов (это может быть больше при обычном использовании).

Дополнительная информация: CandidateProfiles имеет внешний ключ от Candidates, а CandidateId может быть нулевым.

Изменить: мы сделали обходной путь для этой проблемы, но мне действительно интересно, почему этот не будет работать. Simple.Data выглядела забавно сначала, но теперь я не уверен, буду ли я использовать ее в будущем

Ответ 1

Вот объяснение ошибки SQL из http://www.sql-server-helper.com/error-messages/msg-4104.aspx:

Другой способ получения ошибки - это когда псевдоним присвоен таблица, указанная в предложении FROM инструкции, и таблица используется как префикс столбца вместо использования псевдонима.

Хотя это не совсем то, что происходит в вашем случае, оно очень близко. Проблема, которую я вижу с вашим примером кода, находится в вызове FindAll:

        .FindAll(db.dbo.Candidates.CommonOfferId == commonOfferId 
                    && db.dbo.CandidateProfiles.CandidateId == null)
        .LeftJoin(db.dbo.CandidateProfiles, out alias)

Так как FindAll использует полное имя "db.dbo.CandidateProfiles", и каждая другая ссылка использует псевдоним, определенный в следующем LeftJoin, появление в сгенерированное предложение where не использует псевдоним, и вы получаете сочетание и соответствие псевдонимов и явных ссылок на таблицы, что SQL не нравится.

Я думаю, что причина, по которой это произошло только в вашем случае после добавления "Пропустить", - это то, что был создан совершенно другой SQL (моя догадка заключается в том, что только после добавления Skip был использован псевдоним).

Я не понимаю цели условия CandidateProfiles.CandidateId == null (поскольку в сочетании с условием в вызове Вкл. я не вижу, как это никогда не вернет никаких результатов), но я бы предложил добавить ограничения к объединенной таблице в вызове Вкл, чтобы она попала в предложение on вместо где (а затем используя псевдоним вместо полного имени)

.LeftJoin(db.dbo.CandidateProfiles, out alias)  
.On(db.dbo.Candidates.Id == alias.CandidateId && alias.CandidateId == null)