web-dev-qa-db-ja.com

SqlDataReaderから配列(またはarraylist)を埋めます

すべてのアイテムをループすることなく、SqlDataReader(またはその他のC#ADO.NETオブジェクト)を介して配列を埋める方法はありますか?単一の列を返すクエリがあり、それを文字列配列(またはArrayList、Listなど)に入れたい。

23
ristonj

可能です。 .NET 2.0+では、SqlDataReaderDbDataReader(非ジェネリック)を実装するIEnumerableから継承します。これは、LINQを使用できることを意味します。

List<string> list = (from IDataRecord r in dataReader
                     select (string)r["FieldName"]
                    ).ToList();

とはいえ、ループはまだそこにあり、コード内で明示的ではなく、Enumerable.Selectに隠されているだけです。

48
Pavel Minaev

いいえ、SqlDataReaderはSQL Serverデータベースからの順方向専用の読み取り専用の行ストリームであるため、行ストリームはコード内で明示的に、またはフレームワーク実装(DataTableのLoadメソッドなど)で非表示かどうかにかかわらずループします。

一般的なリストを使用し、リストを配列として返すのが適切なオプションのようです。例えば、

List<int> list = new List<int>();

using (SqlDataReader reader = cmd.ExecuteReader())
{
    while (reader.Read())
    {
         list.Add(reader.GetInt32(0));
    }    
}
return list.ToArray();

コメントへの応答として、ToArray()の呼び出しはオーバーヘッドになる場合があります。使用するにはオブジェクトの配列が必要ですか、それとも汎用コレクション(List<T>ReadOnlyCollection<T>など)がより便利ですか?

11
Russ Cam

どうやら、.NET 1.1以降SqlDataReaderには 以下のメソッド がありました。

int size;
object[] data = new object[]{};
size = reader.GetValues(data);

これにより、現在のリーダー行の値がdataに入力され、配列に入れられたオブジェクトの数がサイズに割り当てられます。

6
JNF

IDataReaderの実装(含まれるSqlDataReader)は定義により順方向専用リーダーになるため、ループせずにこれを行う方法はありません。これを行うフレームワークライブラリメソッドがあったとしても、読者と同じように、リーダーをループする必要があります。

4
Andrew Hare

元のOPは、Array、ArrayList、またはListを要求しました。配列も返すことができます。 .ToArray()メソッドを呼び出して、以前に宣言した配列に割り当てます。配列は、各要素の列挙に関して非常に高速です。リストに1000を超える要素がある場合、リストよりもはるかに高速です。配列、リスト、または辞書に戻ることができます。

ids_array = (from IDataRecord r in idReader 
select (string)r["ID"]).ToArray<string>();  

さらに、たとえばキーのルックアップを使用している場合、1つのリストを別のリストと照合してHashSetオブジェクトに要素キーが存在するかどうかを判断するだけで、優れたルックアップパフォーマンスを持つHas​​hSetオブジェクトの作成を検討できます。例:

 HashSet<string> hs = new HashSet<string>( 
(from IDataRecord r in idReader select (string)r["ID"]).AsEnumerable<string>() );
1
RickIsWright

SqlDataAdapterをDataTableに読み込む場合:

DataTable dt as DataTable; 
dt.fill(data);

次に、これに対するJoel Mullerの答えで参照されているように、System.Data.DataSetExtensionsのおもちゃのいくつかを使用できます question。

でLinqを少し使用するので、.Net 3.5以上をネットします。

1
Rob Allen

ループする必要がありますが、それをより簡単にするプロジェクトがあります。また、ArrayListを使用せず、代わりにListを使用してください。

FluentAdoをチェックアウトできます: http://fluentado.codeplex.com

    public IList<UserAccount> List()
    {
        var list = new FluentCommand<UserAccount>("SELECT ID, UserName, Password FROM UserAccount")
            .SetMap(reader => new UserAccount
            {
                ID = reader.GetInt("ID"),
                Password = reader.GetString("Password"),
                UserName = reader.GetString("UserName"),
            })
            .AsList();

        return list;
    }
0
Chris Brandsma