在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个元素要慢得多,因为元数据只需要检索一次,而不是针对每个对象(有更多的原因,但这一个最方便)。

在dbQuery之后运行到OutOfMemoryException

您应该避免将结果一起存储在列表中。主要思想是实例化每个昂贵的对象,处理它,然后立即处理它。

这意味着你的外部方法看起来像:

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);
}
相关文章:
  • 没有找到相关文章