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で確認してみます。

OEM-初期化パラメータ
open_cursorsが 300 となっています。Oracle9i、10gではデフォルト300のようです。(インストール時の値を確認した内容です)
これが影響するんですね。

次はopen cursorsを 500 にして実行した結果です。

ちゃんと、500回目でエラーが出ました。

「なんでそうなるの?」などを追求したい方は、色んな所にテキストがありますが、@マークITのこの記事がわかりやすいので見てみてください。 

まとめ

DataReaderは一回一回きちんとCloseしましょう。

修正履歴

Loading