在dbQuery之后运行到OutOfMemoryException
本文关键字:OutOfMemoryException 运行 之后 dbQuery | 更新日期: 2023-09-27 18:28:19
我正在运行一个DB查询,它返回了相当多的功能(大约100000个)。由于遇到了上述异常,我尝试将查询拆分为几个子查询。但因此,所有这些子查询的结果都被写入方法列表,因此写入内存时,我仍然会遇到相同的异常。
因此,我想知道是否可以在每个子查询完成后,通过循环其元素并返回每个元素来使用yield return
。
在检索到这些特性之后,我必须为它们中的每一个创建一些新的自定义对象,所以我想知道在这种情况下使用yield return是否可以节省内存。
也许以下内容会让它变得更清晰:
foreach (var chunk in IDs.chunk(500))
{
List<ComplexObject> result = new List<ComplexObject>():
// ...
// make a (sub-)query on every chunk to retrieve 500 objects at once
// ..
// now we have up to 500 ComplexObjects within result
foreach (var parcel in result)
{
yield return parcel;
parcel.Release(); // release COM-object
}
}
其中chunk
是500个元素(ID)的(子)集合。
然后,我在foreach
中循环从该方法检索到的结果,并从中创建自定义对象。
EDIT:我也可以逐个查询和处理每个ComplexObject
,事实上,这比检索一堆500个元素要慢得多,因为元数据只需要检索一次,而不是针对每个对象(有更多的原因,但这一个最方便)。
您应该避免将结果一起存储在列表中。主要思想是实例化每个昂贵的对象,处理它,然后立即处理它。
这意味着你的外部方法看起来像:
foreach (var chunk in IDs.SplitIntoChunks(size: 500))
{
foreach (var parcel in EnumerateComplexObjects(chunk))
{
yield return parcel;
}
}
EnumerableComplexObjects
也将使用yield return
:
IEnumerable<ComplexObject> EnumerateObjects(IEnumerable<int> ids)
{
foreach (var id in ids)
{
using (var obj = CreateSingleComplexObject(id))
{
yield return obj;
}
}
}
注意,一旦你这样做了,你甚至不再需要块了:
foreach (var obj in EnumerateObjects(allIDs)
{
Process(obj);
}