先取特定数量的数组再处理
本文关键字:数组 再处理 | 更新日期: 2023-09-27 18:14:10
下面是下面的代码:
InstanceCollection instances = this.MyService(typeID, referencesIDs);
我这里的问题是当referencesIDs.Count()
大于一个特定的计数时,它抛出一个与SQL
相关的错误。
建议我多次调用this.MyService
,这样它就不会处理很多referencesIDs
。
怎么做呢?我正在考虑使用像这样的while循环:
while (referencesIDs.Count() != maxCount)
{
newReferencesIDs = referencesIDs.Take(500).ToArray();
instances = this.MyService(typeID, newReferencesIDs);
maxCount += newReferencesIDs.Count();
}
我在这里看到的问题是,我如何删除newReferencesIDs上的前500个referencesid ?因为如果我不删除第一个循环后的前500,它将继续添加referencesid
您只是想更新referencesIDs
值吗?像这样的?:
referencesIDs = referencesIDs.Skip(500);
那么下次在referencesIDs
上调用.Take(500)
时,它将获得下一个 500个值。
相反,在不更新referencesIDs
变量的情况下,可以在循环中包含Skip
。像这样:
var pageSize = 500;
var skipCount = 0;
while(...)
{
newReferencesIDs = referencesIDs.Skip(skipCount).Take(pageSize).ToArray();
skipCount += pageSize;
...
}
我的第一选择是修复服务,如果你可以访问它。特定于SQL的错误可能是数据库配置不完整的结果,或者是服务器上SQL查询写得不好的结果。例如,Oracle将SQL查询中的IN
列表默认限制为1000项左右,但是您的Oracle DBA应该能够为您重新配置此限制。或者,服务器端程序员可以重写他们的查询,以避免在一开始就达到这个限制。
如果这不起作用,您可以将列表分割成不会触发错误的最大大小块,对服务器进行多次调用,并在您的端组合实例,如下所示:
InstanceCollection instances = referencesIDs
.Select((id, index) => new {Id = id, Index = index})
.GroupBy(p => p.Index / 500) // 500 is the max number of IDs
.SelectMany(g => this.MyService(typeID, g.Select(item => item.Id).ToArray()))
.ToList();
如果您想要将列表分成块的通用方法,您可以使用以下命令:
/// <summary>
/// Split a source IEnumerable into smaller (more manageable) lists.
/// </summary>
public static IEnumerable<IList<TSource>>
SplitIntoChunks<TSource>(this IEnumerable<TSource> source, int chunkSize)
{
long i = 1;
var list = new List<TSource>();
foreach (var t in source)
{
list.Add(t);
if (i++ % chunkSize == 0)
{
yield return list;
list = new List<TSource>();
}
}
if (list.Count > 0)
yield return list;
}
然后你可以使用SelectMany
来使结果变平:
InstanceCollection instances = referencesIDs
.SplitIntoChunks(500)
.SelectMany(chunk => MyService(typeID, chunk))
.ToList();