2

動的エンティティ(Microsoft.Xrm.Sdk.Entity、遅延バインディングメソッドなど)を介してCRM2011データを消費するサービスを開発しています。ソリューションを汎用的に保つために、意図的にXrm.csメソッド(初期バインディング)を使用していません。

また、CRMデータベース(EDMXなど)に直接接続することは避けたいと思います。これにより、ホストされたCRMでソリューションを使用できなくなります(DBに直接アクセスできない場合など)。

次の(簡略化された)要件がありますが、選択基準に本当に苦労しています。

レコードのランダムな7%を選択(および更新)する必要があります。

SQLでは、選択基準は比較的簡単です。ランダムな割合のレコードを選択する方法を知っています。何かのようなもの:

SELECT TOP 7 PERCENT * FROM
(
    SELECT TOP 1000 NEWID() AS Foo, [someColumns]
    FROM [someTable]
)
AS Bar ORDER BY Bar.Foo ASC

これは完全に機能します。LINQに相当するものは次のようなものです。

from e in someEntities
orderby Guid.NewGuid()
select e;

ただし、問題があります。CRM2011動的エンティティでLINQを使用する方法がわかりません。代わりに、このページ(MSDN)に示すように、制限付きのQueryExpressionクラス/構文またはfetchXMLのいずれかを使用する必要があります。

この要件を満たすために、次のオプションを特定しました。

  1. 動的エンティティを使用して、レコードセット全体をリストに戻し、インデックスでランダムに選択するだけです。ただし、これにはインターネットデータサービスを介して最大10,000レコードを返すことが含まれ、低速/安全でないなどの可能性があります。

  2. fetchXMLステートメントを使用します。残念ながら、私はfetchXMLを知らないので、COUNT、TOP、PERCENT、NEWID()などを実行できるかどうかわかりません。

  3. Xrm.csとLINQを使用するか、ストアドプロシージャまたはSQLビューを使用します。これらのオプションはすべて、ソリューションをデータベースへの直接接続または早期バインディング、あるいはその両方に結び付けることを意味しますが、これは望ましくありません。

  4. お客様にノーと言ってください。

アドバイスをいただければ幸いです。fetchXMLはこのクエリを実行できますか?これを行うためのより良い方法はありますか?

4

2 に答える 2

2

FetchXMLはこれをサポートしていないため、1または3になります。CRMOnline製品を使用してSQLに直接接続できないため、3はオンプレミスバージョンでのみ機能します。ただし、顧客がCRM Onlineに移行することが絶対に確実でない限り、これを使用します。1を使用する必要がある場合は、少なくとも、返される列をレコードのGUIDのみに制限して、ペイロードサイズを減らすことができます。次に、ランダムレコードを選択するときに、必要に応じて追加の列を取得します(もちろん、処理するランダムレコードの数によっては、「おしゃべり」のためにこれが遅くなる可能性があります)。

于 2011-09-15T18:03:59.533 に答える
2

Dynamics CRM 2011は、現時点では、SQLや他のLINQプロバイダーが提供できる程度のクエリ能力を提供できないため、お客様にノーと言ってそのような柔軟性が必要な場合は、オンプレミスバージョンに移行してください。

そうは言っても、方法#1の変形は、すべての行を一度にフェッチしてからランダムセットを選択するのではなく、必要な行数になるまで、エンティティから一度に1行ずつランダムセットをフェッチすることです。このメソッドの欠点は、DBを1回呼び出す代わりに多くの呼び出しが行われるため、全体的な取得速度が低下することです。POCは以下のとおりです。

#2に関しては、fetchXmlを使用して、ある程度の成功を収めて、すべての要求を処理できると思います。実際、集約データを取得する唯一の方法は、fetchXmlを使用することであり、ページングもサポートしています。

#3に関しては、この時点でデータから必要なものをすべて取得するにはネイティブSQLが最善の策ですが、それにもかかわらず、LINQプロバイダーは制限されていますが、SQLステートメントをLINQに移行する方がfetchXMLよりもはるかに簡単です。遅延バインディング/動的エンティティをサポートします。

//create a list of random numbers
List<int> randomNumbers = new List<int>();

//declare a percentage of records you'd like to retrieve
double pctg = 0.07;

//use FetchXML to count the # of rows in the table
string fetchXml = @"<fetch aggregate='true'>
<entity name='salesorder'>
<attribute name='salesorderid' aggregate='count' alias='countIds' distinct='false' />
</entity>
</fetch>";
EntityCollection result = _service.RetrieveMultiple(new FetchExpression(fetchXml));
int rowCount = int.Parse(result.Entities[0].FormattedValues["countIds"].Replace(",", ""));

//initalize the random number list for paging
for (int i = 0; i < Math.Ceiling(pctg * rowCount); i++)
{
    randomNumbers.Add((new Random(unchecked((int)(DateTime.Now.Ticks >> i)))).Next(rowCount - 1));
}
randomNumbers.Sort();

//page through the rows one at a time until you have the number of rows you want
using (OrganizationServiceContext osc = new OrganizationServiceContext(_service))
{
    foreach (int r in randomNumbers)
    {
        foreach (var er in (from c in osc.CreateQuery("salesorder")
                            //not especially useful to use the orderby option as you can only order by entity attributes
                            //orderby c.GetAttributeValue<string>("name")
                            select new
                            {
                                name = c.GetAttributeValue<string>("name")
                            }).Skip(r).Take(1))
        {
            Console.WriteLine(er.name);
        }

    }
}
于 2011-09-17T06:45:25.717 に答える