1

CRM2011linqプロバイダーが舞台裏で自動的にページングを実行することを考えると。linqクエリの実行時にフェッチされるレコード数の上限を設定する方法はありますか(ページング用のQueryExpressionでPagingInfo.Countを設定するのと同様)

更新のために約2万件以上のレコードをプルする必要があるシナリオがあります(レコードセットをさらにフィルタリングすることはできませんし、必要もありません)。理想的には、Skip&Take演算子を使用することをお勧めしますが、Countはサポートされていないため、スキップするレコードの数と、さらにレコードのフェッチを停止するタイミングをどのように知ることができますか。

理想的には、TPLを使用し、たとえば3Kまたは5Kレコードのバッチを並行して処理して、スループットを向上させ、ブロックする必要がないようにします。OrganizationserviceContextは、私が知っていることからスレッドセーフではありません。この場合、Parallel.ForまたはParallel.ForEachを使用してデータセットを分割する方法を示す良い例はありますか?どのようにパーティションを作成し、パーティションごとに異なるコンテキストオブジェクトを使用する必要がありますか?

ありがとう。

更新:これが私が思いついたものです:アイデアは、処理するレコードの総数を取得し、PLINQを使用して、タスクごとに新しいOrganizationServiceContextオブジェクトを使用してタスク全体のデータの各サブセットの処理をファームアウトすることです。

static void Main(string[] args)
    {  
       int pagesize = 2000;
        // use FetchXML aggregate functions to get total count
        // Reference: http://msdn.microsoft.com/en-us/library/gg309565.aspx
        int totalcount = GetTotalCount();

       int totalPages = (int)Math.Ceiling((double)totalcount / (double)pagesize);            
       try
        {
            Parallel.For(0, totalPages, () => new MyOrgserviceContext(),
                (pageIndex, state, ctx) =>
                {

                    var items = ctx.myEntitySet.Skip((pageIndex - 1) * pagesize).Take(pagesize);
                    var itemsArray = items.ToArray();
                    Console.WriteLine("Page:{0} - Fetched:{1}", pageIndex, itemsArray.Length);
                    return ctx;
                },
                ctx => ctx.Dispose()
                );
        }
        catch (AggregateException ex)
        {
           //handle as needed
        }
   }
4

1 に答える 1

3

したがって、これを行う方法は、レコードがなくなるまでスキップアンドテイクを使用してレコードをクエリし続けることです。

以下の私の例を確認してください。簡単にするためにintを使用していますが、このアプローチはLinq-to-Crmにも適用されます。

したがって、クエリを実行し続け、前のレコードをスキップして、そのページに必要なレコードを取得し、最後にカウントして、ページ全体を受信したかどうかを確認します。受信しなかった場合は、レコードが不足しています。

コード

List<int> ints = new List<int>()
{
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
};

int pageNumber = 0;
int recordsPerPage = 3;

while(true)
{
    IEnumerable<int> page = ints.Where(i => i < 11).Skip(recordsPerPage * pageNumber).Take(recordsPerPage);

    foreach(int i in page)
    {
        Console.WriteLine(i);
    }

    Console.WriteLine("end of page");
    pageNumber++;

    if (page.Count() < recordsPerPage)
    {
        break;
    }
}

出力:

1
2
3
end of page
4
5
6
end of page
7
8
9
end of page
10
end of page
于 2012-09-20T19:56:56.170 に答える