今回は、SELECTについて。SELECT結果はObjectで返ってくる上、サイズが不明なため、処理的には汚い感じになる。
実際の処理
public string[][] ExecuteReturn(string sql) { //DBを開く if (open()) { try { //クエリの実行 command.CommandText = sql; using (SQLiteDataReader sdr = command.ExecuteReader()) { List<string[]> tuples = new List<string[]>(); for (int i = 0; sdr.Read(); i++) { string[] column = new string[sdr.FieldCount]; for (int j = 0; j < sdr.FieldCount; j++) { column[j] = sdr[j].ToString(); } tuples.Add(column); } //DBを閉じる close(); //リストを配列に変換して返す return tuples.ToArray(); } } catch (Exception ex) { //DBが例外を吐いた場合 error(ex.ToString()); //DBを閉じる close(); } } //失敗 return null; }
using構文について
using (SQLiteDataReader sdr = command.ExecuteReader())
using構文の使い方について、一応軽く触れておく。
usingの中身の資源は、その処理が終わったときに必ず破棄されることが保障される。C#はガーベージコレクションという機構で、参照されなくなったオブジェクトは自動で、いつの間にか破棄される。そのため、いつ破棄されるか分からない以上、資源を任せておけるはずもない。だから、明示的にDispose()するか、usingを使うのが適当。
ExecuteReader()について
前回までは、ExecuteNonQuery()だったものが、今回はExecuteReader()となる。ここで、やっと「NonQuery」という言葉の意味が分かってくることだろう。
sdr.Read()
これで、SELECT結果の次の行へ移動できるらしく、更に、次の行が存在しないときは、うまい具合にループを抜けてくれるようだ。
受け取ったデータの加工
Objectの配列の配列みたいな形式で戻ってくるため、それをToString()してリストに追加しとく(なぜリストかと言うと、SELECT結果が何個あるか、予想がつかないため)。後は、それらをToArray()で配列として使いやすくし、返す。
とりあえず、この当たりで全体的な説明は終わったはず。