2

私が行う作業には、SQLサーバーデータベースから大量のデータをメモリにダウンロードすることが含まれます。これを実現するために、SqlDataReaderを使用してロードするカスタムデータセット定義を用意し、Datatableを反復処理して各行をオブジェクトに構築し、通常はそれらのオブジェクトを大規模なディクショナリにパッケージ化します。

使用しているデータの量が十分に多いため、メモリの上限がある単一のデータテーブルに収まらない場合があります。辞書は、最も極端なケースでは8GBのシステムメモリを超えるほど大きくなりました。私は、データテーブルがオーバーフローしたときにスローされるメモリ不足の例外を修正するタスクを与えていました。これは、データテーブルの使用方法と矛盾しているように見えるバッチプロセスメソッドを実装することで実現しましたが、当面は機能しました。

私は今、このプロセスのメモリ要件をさらに削減するタスクを持っています。私の考えは、SqlDataReaderを受け取り、基本的にリーダーを列挙しているコレクションとして使用するIEnumeratorを継承する一般的に型指定されたクラスを作成することです。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))
    {
        ...
    }
}

注意が必要な場合は、LINQtoObjectsを使用することもできます。

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 に答える