DataReader クローズしないとどうなるの??
使い終わったら、必ずクローズしてね..
と、いわれて来たのであまり考えずにDataReaderをクローズするよう記述しているのだけれど、実際どうなるのかわからなかったので、やってみました。
DataReaderは、カーソルが戻される?
OracleDataReaderを使ってデータを取得する、という事は
- 「ExecuteReader」メソッドを実行しOracle上に条件を満たすレコードが確保され、
- そのレコードを読み出す為の「カーソル情報」が戻り値として返ってくる。
という事のようです。
Closeメソッドでは
その「カーソル」を閉じて破棄するのでしょう。
やってみる
プログラム
指定したループ回数、EMPテーブルを読みSAL列を合計するプログラムで実験。
Private Sub DR_CloseTest(ByVal isCloseDataReader As Boolean, ByVal LoopCount As Integer) Const cmdSelect As String = _ "select " & _ "EMPNO, ENAME, JOB, MGR, HIREDATE, nvl(SAL,0) SAL, COMM, DEPTNO " & _ "from EMP" Dim i As Integer Dim rd As Ora.OracleDataReader = Nothing Dim Total_Sal As Decimal = 0D Try CountExecute += 1 Using cn As New Ora.OracleConnection(clsGlobal.gConnetionString) cn.Open() Using cmd As New Ora.OracleCommand(cmdSelect, cn) For i = 0 To LoopCount - 1 rd = cmd.ExecuteReader While rd.Read Total_Sal += CDec(rd.Item("SAL")) End While If isCloseDataReader Then rd.Close() End If Next End Using cn.Close() End Using ListBox1.Items.Add(CountExecute.ToString & "回目 : SAL Total = " & Total_Sal.ToString) Catch ex As Ora.OracleException ListBox1.Items.Add("Oracle Error " & CountExecute.ToString & _ "回目 : LoopCount=" & i.ToString & _ " " & ex.Message) MessageBox.Show(ex.Message) Catch ex As Exception ListBox1.Items.Add("Error " & CountExecute.ToString & _ "回目 : LoopCount=" & i.ToString & _ " " & ex.Message) MessageBox.Show(ex.Message) Finally If Not IsNothing(rd) Then If isCloseDataReader Then rd.Close() End If End If End Try End Sub
見てもらうとわかりますが、1回目と2回目はDataReaderをCloseしなかった結果です。
それに対して3回目、4回目はCloseした結果です。
300回目でエラーが出ました。300が「最大オープンカーソル数」だと言えそうです。
最大オープンカーソル数を確認
OracleEnterpriseManagerで確認してみます。
open_cursorsが 300 となっています。Oracle9i、10gではデフォルト300のようです。(インストール時の値を確認した内容です)
これが影響するんですね。
次はopen cursorsを 500 にして実行した結果です。
ちゃんと、500回目でエラーが出ました。
「なんでそうなるの?」などを追求したい方は、色んな所にテキストがありますが、@マークITのこの記事がわかりやすいので見てみてください。
まとめ
DataReaderは一回一回きちんとCloseしましょう。