2

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

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

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

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

另外,从逻辑上讲:当调用 Current 属性时,我将如何调用类型声明所需的特定构建器函数?

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

4

1 回答 1

3

使用迭代器块似乎相当明智,实际上非常简单:

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...
}
于 2012-08-08T15:49:30.333 回答