0

Linqを使用してMSCRM2011Webサービスにクエリを実行しています。SQLが非常に貧弱になるクエリがあり、中間データを取得しすぎて、パフォーマンスがひどいです。私はそれに慣れていないので、それは私がそれを使用している方法である可能性が非常に高いです...

NN関係を介してリンクされた2つのエンティティがあります:ProductSalesLinkProduct私は彼らから彼らに関連するSerialNumberすべてのものと一緒にたくさんを取り戻したいですSalesLink

これは私がPredicateBuilderを使用しているクエリです:

// Build inner OR predicate on Serial Number list
var innerPredicate = PredicateBuilder.False<Xrm.c_product>();
foreach (string sn in serialNumbers) {
   string temp = sn; // This temp assignement is important!
   innerPredicate = innerPredicate.Or(p => p.c_SerialNumber == temp);
}

// Combine predicate with outer AND predicate
var predicate = PredicateBuilder.True<Xrm.c_product>();
predicate = predicate.And(innerPredicate);
predicate = predicate.And(p => p.statecode == (int)CrmStateValueType.Active);

// Inner Join Query
var prodAndLinks = from p in orgContext.CreateQuery<Xrm.c_product>().AsExpandable()
                                                                    .Where(predicate)
                                                                    .AsEnumerable()
                   join link in orgContext.CreateQuery<Xrm.c_saleslink>()
                        on p.Id equals link.c_ProductSalesLinkId.Id
                   where link.statecode == (int)CrmStateValueType.Active
                   select new {
                         productId = p.Id
                       , productSerialNumber = p.c_SerialNumber
                       , accountId = link.c_Account.Id
                       , accountName = link.c_Account.Name
                   };
...

SQLプロファイラーを使用すると、WHERE句のない中間SQLクエリが発生し、次のようになります。

select 
top 5001 "c_saleslink0".statecode as "statecode"
  ...
, "c_saleslink0".ModifiedOnBehalfByName as "modifiedonbehalfbyname"
, "c_saleslink0".ModifiedOnBehalfByYomiName as "modifiedonbehalfbyyominame" 
from
 c_saleslink as "c_saleslink0" order by
 "c_saleslink0".c_saleslinkId asc

これにより、大量の(役に立たない)データが返されます。結合はDB側ではなくクライアント側で行われると思います...

このクエリをどのように改善する必要がありますか?私は約3分で走りますが、それはまったく受け入れられません。

ありがとう。


"解決"

Linq to CRMの代わりにQueryExpressionを使用するというDarylの回答に基づいて、まったく同じ結果が得られるようになりました。

var qe = new QueryExpression("c_product");
qe.ColumnSet = new ColumnSet("c_serialnumber");
var filter = qe.Criteria.AddFilter(LogicalOperator.Or);
filter.AddCondition("c_serialnumber", ConditionOperator.In, serialNumbers.ToArray());
var link = qe.AddLink("c_saleslink", "c_productid", "c_productsaleslinkid");
link.LinkCriteria.AddCondition("statecode", ConditionOperator.Equal, (int)CrmStateValueType.Active);
link.Columns.AddColumns("c_account");
var entities = serviceProxy.RetrieveMultiple(qe).Entities.ToList();;

var prodAndLinks = entities.Select(x => x.ToEntity<Xrm.c_product>()).Select(x => 
                   new {
                      productId = x.c_productId
                    , productSerialNumber = x.c_SerialNumber
                    , accountId = ((Microsoft.Xrm.Sdk.EntityReference)((Microsoft.Xrm.Sdk.AliasedValue)x["c_saleslink1.c_account"]).Value).Id
                    , accountName = ((Microsoft.Xrm.Sdk.EntityReference)((Microsoft.Xrm.Sdk.AliasedValue)x["c_saleslink1.c_account"]).Value).Name
                   }).ToList();

Linqを使用して解決策を見つけたかったのですが、LinqtoCRMはまだ存在しないようです...

4

2 に答える 2

1

CRM の複雑なクエリでパフォーマンスの問題が発生している場合の 95% の場合、パフォーマンスを改善する最も簡単な方法は、データベースに対して単純な SQL クエリを実行することです (もちろん、これが CRM オンラインではないと仮定します)。これは 5% のうちの 1 つかもしれません。

あなたの場合、発生している主要なパフォーマンスの問題は、述語ビルダーが CRM サーバー (SQL データベースではない) 側のデータ結合を強制するためです。クエリ式 (リンク ステートメントが変換されるもの) を使用した場合は、IN 演算子を使用して条件式を指定し、serialNumbers コレクションを渡すことができます。FetchXml も使用できます。これらの方法は両方とも、CRM が SQL 側の結合を実行できるようにします。

編集:

これにより、クエリ式で 80% の方法が得られるはずです。

IOrganizationService service = GetService();
var qe = new QueryExpression("c_product");
var filter = qe.Criteria.AddFilter(LogicalOperator.Or);
filter.AddCondition("c_serialnumber", ConditionOperator.In, serialNumbers.ToArray());
var link = qe.AddLink("c_saleslink", "c_productid", "c_productsaleslinkid");
link.LinkCriteria.AddCondition("statecode", ConditionOperator.Equal, (int)CrmStateValueType.Active);
link.Columns.AddColumns("c_Account");
var entities = service.RetrieveMultiple(qe).Entities.ToList();
于 2012-09-21T11:30:02.830 に答える
0

おそらく、Linq to Crm を使用しないことで、より適切に制御できることがわかるでしょう。あなたは試すことができます:

  1. FetchXml、これは tsql MSDNへのアプローチに似た xml 構文です。

  2. QueryExpressionMSDN

  3. RetrieveRequestブログを発行できます。

于 2012-09-20T20:07:52.853 に答える