我有以下情况:
有两种相关的类型。对于这个问题,我将使用以下简单类型:
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; } }
所以那个
Person
可能有多个Account
s(即多个Account
s 将引用相同的PersonId
)。在我们的数据库中,有几万人,平均每个人有5-10个账户。
我需要检索每个人的帐户,假设他们满足特定要求。之后,我需要查看此人的所有帐户是否一起满足另一个条件。
在这个例子中,假设我需要
amount < 100
的每个帐户,并且在检索到一个人的帐户后,我需要检查他们的总和是否大于 1000。使用 LINQ 查询是可取的,但不能使用
group-by-into
来完成关键字,因为 Linq-Provider (LINQ-to-CRM) 不支持它。此外,执行以下简单的 LINQ 查询来实现 list 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)
不可能有两个原因:
一个。 Linq-Provider 强制调用
ToList()
使用前GroupBy()
.尝试实际调用
ToList()
使用前GroupBy()
结果是 内存不足异常 - 因为有数以万计的帐户。出于效率原因,我不想执行以下操作,因为这意味着数万次检索:
一个。检索所有人。
遍历它们并在每次迭代中检索每个人的帐户。
会很高兴有有效的想法。
最佳答案
我建议通过 PersonId
对查询进行排序,通过 AsEnumerable()
切换到 LINQ to Objects(从而执行它,但不会在内存中实现整个结果集,例如ToList()
调用),然后使用 GroupAdjacent
方法来自 MoreLINQ包裹:
This method is implemented by using deferred execution and streams the groupings. The grouping elements, however, are buffered. Each grouping is therefore yielded as soon as it is complete and before the next grouping occurs.
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);
AsEnumerable()
技巧肯定适用于 EF 查询提供程序。它是否与 LINQ to CRM 提供程序一起工作实际上取决于提供程序如何实现 GetEnumerator()
方法 - 如果它试图缓冲整个查询结果,那么您就不走运了。
关于c# - 在多重限制下检索大量记录,不会导致内存不足异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44892308/