LINQ to Dynamics CRM Запрос на локальную фильтрацию записей - PullRequest
12 голосов
/ 09 февраля 2011

Я написал запрос Linq to CRM с помощью CRM 2011 RC (v5) поставщика LINQ-to-CRM.У меня есть локально объявленный список , который я хочу присоединить к объекту CRM, и я хочу, чтобы запрос выполнялся на сервере CRM.Пример может помочь:

MyObject myObject = new MyObject();
List<myAccount> myAccountsList = new List<myAccount>();

myAccountsList.Add(new myAccount() {AccountNumber = "123"};
myAccountsList.Add(new myAccount() {AccountNumber = "456"};

myObject.ListOfAccounts = myAccountsList;

var accountsQuery = from ax in myObject.ListOfAccounts
                    join a in orgContext.CreateQuery<customAccountEntity>() on ax.AccountNumber equals a.account_number
                    select a;

foreach(var item in accountsQuery)
{
    Console.WriteLine("Id of record retrieved: " + a.Id.ToString());
}

Приведенный выше код компилируется и выполняется, однако фильтрация записей выполняется локально после получения всего набора записей сущности CRM.Очевидно, что когда сущность CRM содержит тысячи строк, запрос будет работать плохо или даже по таймауту.

Я прочитал об IQueryable и IEnumerable и попытался преобразовать список с помощью метода расширения AsQueryable (), который не дал эффекта.Мне нужен мой вышеупомянутый запрос Linq для запуска SQL следующим образом:

SELECT a.*
FROM customAccountEntity AS a
WHERE a.account_number IN ('123', '456');

Или с использованием временной таблицы, если требуется объединить несколько полей.Как мне это сделать?

Ответы [ 3 ]

13 голосов
/ 01 марта 2011

После долгих попыток и исследований я решил проблему с помощью Predicate Builder и LINQKit .Мне нужно создать предикат на основе Or, используя keys в моем локальном списке , а затем передать предикат в метод расширения Where LINQ.Важно отметить, что мне нужно вызвать метод расширения AsExpandable , предоставляемый LINQKit.Мой код будет выглядеть так:

var predicate = PredicateBuilder.False<customAccountEntity>();
// Loop through the local List creating an Or based predicate
foreach (var item in myAccountsList)
{
    string temp = item.AccountNumber;
    predicate = predicate.Or (x => x.customCrmEntityAttribute == temp);
}
// The variable predicate is of type Expression<Func<customAccountEntity, bool>>
var myLinqToCrmQuery =  from ax in myObject.ListOfAccounts
                        from cx in orgContext.CreateQuery<customAccountEntity>().AsExpandable().Where(predicate)
                        where ax.AccountNumber == cx.account_number
                        select cx;

foreach (resultItem in myLinqToCrmQuery)
{
    Console.WriteLine("Account Id: " + resultItem.Id);
}

Приведенный выше код будет запускать оператор SQL на сервере CRM следующим образом:

SELECT a.*
FROM customAccountEntity AS a
WHERE a.account_number = '123' OR a.account_number = '456'

Это означает, что я могу создать динамическое предложение whereво время выполнения и знаю, что мой запрос будет запускать логику фильтрации на CRM SQL Server.Надеюсь, это поможет кому-то еще.

1 голос
/ 09 мая 2011

Вместо того, чтобы играть с предикатами, вы также можете просто использовать выражение объединения для фильтрации.

var myLinqToCrmQuery =  from ax in myObject.ListOfAccounts
                            join cx in orgContext.CreateQuery<customAccountEntity> on ax.AccountNumber equals cx.account_number                      
                            select cx;

Ура, Лукаш

0 голосов
/ 09 февраля 2011

Редактировать: Попробуйте это:

MyObject myObject = new MyObject();
List<myAccount> myAccountsList = new List<myAccount>();

myAccountsList.Add(new myAccount() {AccountNumber = "123"};
myAccountsList.Add(new myAccount() {AccountNumber = "456"};

myObject.ListOfAccounts = myAccountsList;

var accountNumbers = myObject.ListOfAccounts.Select(a => a.AccountNumber);

var accountsQuery = orgContext.CreateQuery<customAccountEntity>()
                              .Where(a => accountNumbers.Contains(a.account_number));

foreach(var item in accountsQuery)
{
    Console.WriteLine("Id of record retrieved: " + a.Id.ToString());
}

Редактировать: если ваш поставщик запросов не поддерживает Contains, создайте условие Where с несколькими ИЛИ, вы можете использовать построитель предикатов длясделать это легко

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...