すべてのアイテムをループすることなく、SqlDataReader(またはその他のC#ADO.NETオブジェクト)を介して配列を埋める方法はありますか?単一の列を返すクエリがあり、それを文字列配列(またはArrayList、Listなど)に入れたい。
可能です。 .NET 2.0+では、SqlDataReader
はDbDataReader
(非ジェネリック)を実装するIEnumerable
から継承します。これは、LINQを使用できることを意味します。
List<string> list = (from IDataRecord r in dataReader
select (string)r["FieldName"]
).ToList();
とはいえ、ループはまだそこにあり、コード内で明示的ではなく、Enumerable.Select
に隠されているだけです。
いいえ、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>
など)がより便利ですか?
どうやら、.NET 1.1以降SqlDataReader
には 以下のメソッド がありました。
int size;
object[] data = new object[]{};
size = reader.GetValues(data);
これにより、現在のリーダー行の値がdata
に入力され、配列に入れられたオブジェクトの数がサイズに割り当てられます。
IDataReader
の実装(含まれるSqlDataReader
)は定義により順方向専用リーダーになるため、ループせずにこれを行う方法はありません。これを行うフレームワークライブラリメソッドがあったとしても、読者と同じように、リーダーをループする必要があります。
元のOPは、Array、ArrayList、またはListを要求しました。配列も返すことができます。 .ToArray()メソッドを呼び出して、以前に宣言した配列に割り当てます。配列は、各要素の列挙に関して非常に高速です。リストに1000を超える要素がある場合、リストよりもはるかに高速です。配列、リスト、または辞書に戻ることができます。
ids_array = (from IDataRecord r in idReader
select (string)r["ID"]).ToArray<string>();
さらに、たとえばキーのルックアップを使用している場合、1つのリストを別のリストと照合してHashSetオブジェクトに要素キーが存在するかどうかを判断するだけで、優れたルックアップパフォーマンスを持つHashSetオブジェクトの作成を検討できます。例:
HashSet<string> hs = new HashSet<string>(
(from IDataRecord r in idReader select (string)r["ID"]).AsEnumerable<string>() );
SqlDataAdapterをDataTableに読み込む場合:
DataTable dt as DataTable;
dt.fill(data);
次に、これに対するJoel Mullerの答えで参照されているように、System.Data.DataSetExtensions
のおもちゃのいくつかを使用できます question。
でLinqを少し使用するので、.Net 3.5以上をネットします。
ループする必要がありますが、それをより簡単にするプロジェクトがあります。また、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;
}