12

CRM 2011 RC(v5)LINQ-to-CRMプロバイダーを使用してLinqtoCRMクエリを作成しました。CRMエンティティに参加したいローカルで宣言されたList<T>があり、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()拡張メソッドを使用してリストを変換しようとしましたが、効果はありませんでした。次のようなSQLを実行するには、上記のLinqクエリが必要です。

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

または、複数のフィールドで結合する場合は、一時テーブルを使用します。どうすればこれを達成できますか?

4

3 に答える 3

13

多くのヘッドバンギングと調査の後、Predicate BuilderLINQKitを使用して問題を解決しました。ローカル List<T>のキーを使用して Or ベースの述語を作成し、その述語を Where LINQ 拡張メソッドに渡す必要があります。重要なのは、 LINQKit によって公開されるAsExpandable拡張メソッドを呼び出す必要があることです。したがって、私のコードは次のようになります。

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

上記のコードは、次のように CRM サーバーで SQL ステートメントを実行します。

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

つまり、実行時に動的な where 句を作成し、クエリが CRM SQL Server でフィルタリング ロジックを実行することを確認できます。これが他の誰かに役立つことを願っています。

于 2011-03-01T09:59:49.953 に答える
0

編集:それを試してください:

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をサポートしていない場合は、複数のORを使用してWhere条件を作成し、述語ビルダーを使用して簡単にすることができます

于 2011-02-09T11:35:56.373 に答える