绑定到数据库的自定义通用 IEnumerator

本文关键字:IEnumerator 自定义 数据库 绑定 | 更新日期: 2024-11-05 10:43:05

我所做的工作涉及从SQL服务器数据库下载大量数据到内存中。为了实现这一点,我们有自定义数据集定义,我们使用 SqlDataReader 加载这些定义,然后循环访问 Datatable 并将每一行构建到一个对象中,然后通常将这些对象打包到一个庞大的字典中。

我们使用的数据量足够大,有时它无法放入具有内存上限的单个数据表中。在最极端的情况下,字典甚至已经变得足够大,可以超过8 GB的系统内存。我的任务是修复数据表溢出时抛出的内存不足异常。我通过实现一个批处理方法来实现这一点,该方法似乎与数据表的使用方式相冲突,但它暂时有效。

我现在的任务是进一步减少此过程的内存需求。我的想法是创建一个继承自 IEnumerator 的通用类型类,该类采用 SqlDataReader,本质上使用读取器作为它正在枚举的集合。MoveNext() 函数将推进读取器,Current 属性将从读取器的当前行返回从生成器方法生成的指定类型化对象。

我的问题:这是一个可行的想法吗?我从未听说过/无法在网上找到类似的东西。

此外,逻辑上:调用 Current 属性时,我将如何调用类型声明所需的特定生成器函数?

我愿意接受批评和责备,因为我想出了一个愚蠢的想法。我最感兴趣的是找到接近总体目标的最佳实践。

绑定到数据库的自定义通用 IEnumerator

看起来相当明智,实际上使用迭代器块非常简单:

private static IEnumerable<Foo> WrapReader(SqlDataReader reader)
{
    while (reader.Read())
    {
        Foo foo = ...; // TODO: Build a Foo from the reader
        yield return foo;
    }
}

然后,您可以将其与:

using (SqlDataReader reader = ...)
{
    foreach (Foo foo in WrapReader(reader))
    {
        ...
    }
}

如果您小心,甚至可以使用 LINQ to Objects:

using (SqlDataReader reader = ...)
{
    var query = from foo in WrapReader(reader)
                where foo.Price > 100
                select foo.Name;
    // Use the query...
}