2011-06-13 3 views
2

У меня есть требование запросить записи в CRM, что не имеют связанную сущность определенного типа. Обычно я делал это с помощью Left Outer Join, а затем фильтровал для всех строк с NULL в правой части.Dynamics CRM 2011 - Фильтрация запроса LINQ с внешними соединениями

Например:

var query = from c in orgContext.CreateQuery<Contact>() 
      join aj in orgContext.CreateQuery<Account>() 
       on c.ContactId equals aj.PrimaryContactId.Id 
      into wonk 
      from a in wonk.DefaultIfEmpty() 
      where a.Name == null 
      select new Contact 
        { 
         FirstName = c.FirstName, 
         LastName = c.LastName, 
        }; 

Это должно вернуть мне все Contats, которые не Primary Контакт счета. Однако этот запрос заканчивается возвратом всех контактов ...! Когда вы смотрите на SQL, который получает генерируемый в SQL Profiler это выходит так:

SELECT cnt.FirstName, cnt.LastName 
FROM Contact as cnt 
    LEFT OUTER JOIN Account AS acct 
     ON cnt.ContactId = acct.PrimaryContactId AND acct.Name is NULL 

Итак, я получаю Соединение слева Хорошо, но фильтр на оговорке Join, а не в WHERE и не так, как должно быть:

SELECT cnt.FirstName, cnt.LastName 
FROM Contact as cnt 
    LEFT OUTER JOIN Account AS acct 
     ON cnt.ContactId = acct.PrimaryContactId 
WHERE acct.Name is NULL 

Понятно, что результаты этого запроса очень разные! Есть ли способ получить запрос на CRM для создания правильного SQL?

Является ли это ограничением базового запроса FetchXML?

+0

В какой таблице используется столбец «Имя»? –

+0

@ Hassan, Name - это поле объекта Account. Я просто выбрал поле, которое, как я думал, всегда должно иметь данные для этого примера. На самом деле мой запрос не существует между встроенными объектами. – Mark

ответ

7

К сожалению, это ограничение внедрений CRM-LINQ и FetchXML. Эта страница из SDK утверждает внешние соединения не поддерживаются:

http://technet.microsoft.com/en-us/library/gg328328.aspx

И пока я не могу найти официальный документ, есть много результатов там для людей, упоминая FetchXML не поддерживает левое внешнее соединение , например:

http://gtcrm.wordpress.com/2011/03/24/fetch-xml-reports-for-crm-2011-online/

+0

Нечетно, что документы говорят, что, поскольку внешнее соединение действительно работало. Проблема с фильтрацией результатов с правой стороны.Использование raw FetchXML, похоже, имеет ту же проблему. – Mark

+0

Внешние соединения также работали для меня, но у меня были другие проблемы с попыткой добавить соединение к запросу. – BrandonG

+1

Я подтвердил ответ, потому что он кажется правильным, но также разочаровывает, что можно найти в то же время. Мой доступ к данным в CRM становится ужасным соединением запросов LINQ, QueryExpression и ADO.NET в отфильтрованных представлениях, где другие просто не работают. Запросы ADO.NET становятся все более распространенными, поскольку QueryExpression для больших запросов становится слишком разрозненным и трудно увидеть дерево для деревьев, в то время как LINQ (версия CRM), похоже, тускнеет с точки зрения его возможностей :( –

1

Попробуйте это:

var query = from c in orgContext.CreateQuery<Contact>() 
      where orgContext.CreateQuery<Account>().All(aj => c.ContactId != aj.PrimaryContactId.Id)     
      select new Contact 
      { 
        FirstName = c.FirstName, 
        LastName = c.LastName, 
      }; 
+0

Хммм, но я хочу отфильтровать по имени.Name, а не c.Name? – Mark

+0

@Mark. Проверьте мой обновленный ответ. Надеюсь, что поможет –

+0

@ Hassan. Извините, это действительно не сработает - нет учетных записей с именем Null. «A.Name == null» в моем примере запроса пытается выбрать строки без соответствующей учетной записи. – Mark

0

Если вам не нужно обновить объект (например, обработать все соответствующие правила проверки и этапы рабочего процесса), вы можете написать менее уродливые и более эффективные запросы, попав в SQL Server напрямую.

В соответствии с образцом CRM, взгляды заботятся о большинстве общих объединений для вас. Например, таблицы dbo.ContactBase и dbo.ContactExtensionBase уже соединены для вас в представлении dbo.Contact. Учетная запись уже существует (например, AccountIdName для какой-то причудливой причины, но, по крайней мере, она есть).

Смежные вопросы