1

鉴于 CRM 2011 linq 提供程序在幕后自动执行分页。有没有办法设置执行 linq 查询时获取的记录数的上限(类似于在 QueryExpression 上设置 PagingInfo.Count 以进行分页)

我有一个场景,我需要提取大约 20K+ 记录进行更新(不,我不能也不需要进一步过滤记录集)。理想情况下,我更喜欢使用 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

所以我这样做的方法是继续使用skip and take查询记录,直到我用完记录。

看看我下面的例子,为了简单起见,它使用 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 回答