【问题标题】:CRM 2011 server side paging / data parallelism using LINQ provider使用 LINQ 提供程序的 CRM 2011 服务器端分页/数据并行
【发布时间】:2012-09-20 03:21:18
【问题描述】:

鉴于 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
        }
   }

【问题讨论】:

  • 为什么不一次提取所有 20,000 条记录进行更新?无论如何,CRM 将一次请求这些记录 5,001 条记录。
  • 如果我必须阻止直到所有 20K 都在本地获取,那么可扩展性不是很好。我已经更新了问题以使用 Context 对象反映这一点和并行性考虑

标签: dynamics-crm-2011


【解决方案1】:

所以我这样做的方法是继续使用 skip 和 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

【讨论】:

  • 这正是我最终做的,然后看到了你的答案。谢谢!
  • 将您的回复标记为答案,因为它是解决方案的核心...我添加了我想出的解决方案,以便使用 TPL 获得更好的吞吐量
猜你喜欢
  • 2021-04-16
  • 2022-07-18
  • 2011-08-18
  • 1970-01-01
  • 2011-07-31
  • 2015-11-03
  • 2012-08-08
  • 1970-01-01
  • 2016-01-05
相关资源
最近更新 更多