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しましょう。