在多个限制下检索大量记录,而不会导致内存不足异常

Hey*_*ude 5 c# linq database dynamics-crm

我有以下情况:

  1. 有两种相关类型.对于这个问题,我将使用以下简单类型:

    public class Person
    {
         public Guid Id {get; set;}
         public int status {get; set;}
    }
    
    public class Account
    {
         public Guid AccountId {get; set;}
         public decimal Amount { get; set; }
         public Guid PersonId { get; set; }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    所以一个人Person可能有多个Accounts(即多个Accounts会引用相同的s PersonId).

  2. 在我们的数据库中,有成千上万的人,平均每人有5-10个帐户.

  3. 我需要检索每个人的帐户,假设他们满足某些要求.之后,我需要看看这个人的所有账户是否一起满足另一个条件.

    在这个例子中,假设我需要每个帐户amount < 100,并且在检索一个人的帐户后,我需要检查他们的总和是否大于1000.

  4. 使用LINQ查询是可取的,但不能使用group-by-into关键字来完成,因为Linq-Provider(LINQ-to-CRM)不支持它.

  5. 另外,也不可能执行以下简单的LINQ查询来实现清单3的要求(请阅读内联注释):

    var query = from p in personList
                join a in accountList on p.Id equals a.PersonId
                where a.Amount < 100
                select a;
    var groups = query.GroupBy(a => a.PersonId);
    // and now, run in bulks on x groups 
    // (let x be the groups amount that won't cause an out-of-memory exception)
    
    Run Code Online (Sandbox Code Playgroud)

    这有两个原因是不可能的:

    一个.Linq-Provider ToList()在使用之前强制进行呼叫GroupBy().

    ToList()在使用GroupBy()导致内存不足异常之前尝试实际调用- 因为有数万个帐户.

  6. 出于效率原因,我不想执行以下操作,因为它意味着成千上万的检索:

    一个.检索所有人.

    湾 循环遍历它们并在每次迭代时检索每个人的帐户.

对高效的想法感到高兴.

Iva*_*oev 5

我建议按顺序排序查询PersonId,切换到LINQ to Objects via AsEnumerable()(因此执行它,但不在内存中实现整个结果集,如ToList()调用),然后使用MoreLINQ包中的GroupAdjacent方法:

此方法通过使用延迟执行实现并对分组进行流式处理.但是,分组元素是缓冲的.因此,每个分组一旦完成并在下一个分组发生之前就会产生.

var query = from p in personList
            join a in accountList on p.Id equals a.PersonId
            where a.Amount < 100
            orderby a.PersonId
            select a;
var groups = query.AsEnumerable()
    .GroupAdjacent(a => a.PersonId)
    .Where(g => g.Sum(a => a.Amount) > 1000);
Run Code Online (Sandbox Code Playgroud)

这个AsEnumerable()技巧肯定适用于EF查询提供商.它是否适用于LINQ to CRM提供程序实际上取决于提供程序如何实现GetEnumerator()方法 - 如果它尝试缓冲整个查询结果,那么你就不走运了.