TOP > ADO.NETとOracle

Oracle Data Reader の Closeメソッド について

ODP.NETのDataReaderに限らず、DataReader(面倒なのでDRと略します)使い終わったらCloseしないとエライ事になるとの事でいつもなるべく早くCloseしているのがクセになっています。でも、人のプログラムを見ているとCloseしないでいるのもよく見ちゃいます。

カーソルを閉じないと言うことなので、DBに負担をかけると思うのですが、それで運用出来ているのだからたまたま影響が出ていないのでしょうか?それともどこかで破綻するのでしょうか?破綻するとしたらどこで破綻するのでしょうか?

 

DBの「最大オープンカーソル数」の設定値で破綻するんですね。
Oracleの場合「ORA-01000 最大オープン・カーソル数を超えました。」とエラーが吐かれます。

Oracle9i、10gではデフォルト300です。

実験

ZAIKOFLGという列がある「TEST」テーブル(20行)のZAIKOFLGを加算して表示するだけのプログラムです。


Imports Oracle.DataAccess.Client

Public Class Form1

    Private CountOfExecute As Integer = 0

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="isClose"></param>
    ''' <remarks></remarks>
    Private Sub CloseTest( _
        ByVal LoopCount As Integer, ByVal isClose As Boolean)
        
        Dim Cn As OracleConnection = Nothing
        Dim cmd As OracleCommand = Nothing
        Dim rd As OracleDataReader = Nothing

        Dim i As Integer
        Dim SumValue As Decimal = 0D

        Try
            CountOfExecute += 1

            Cn = New OracleConnection( _
                 My.Settings.ConnectionString)
            cmd = New OracleCommand("", Cn)

            Cn.Open()

            cmd.CommandText = "select * from TEST"

            For i = 0 To LoopCount - 1
                SumValue = 0D
                rd = cmd.ExecuteReader
                While rd.Read
                    SumValue += CDec(rd.Item("ZAIKO"))
                End While

                If isClose Then
                    rd.Close()
                End If

            Next

            ListBox1.Items.Add(CountOfExecute.ToString & _
                 "回目 : ZAIKO Total = " & SumValue.ToString)

        Catch ex As Oracle.DataAccess.Client.OracleException
            ListBox1.Items.Add("Oracle Error " & _
            CountOfExecute.ToString & _
            "回目 : LoopCount=" & i.ToString & _
            " " & ex.Message)
            MessageBox.Show(ex.Message)


        Catch ex As Exception
            ListBox1.Items.Add(CountOfExecute.ToString & _
            "回目 : LoopCount=" & i.ToString & " " & ex.Message)
            MessageBox.Show(ex.Message)

        Finally
            If Not IsNothing(rd) Then
                If Not rd.IsClosed Then
                    rd.Close()
                End If
                rd.Dispose()
            End If
            If Not IsNothing(cmd) Then
                cmd.Dispose()
            End If
            If Not IsNothing(Cn) Then
                If Cn.State = ConnectionState.Open Then
                    Cn.Close()
                End If
                Cn.Dispose()
            End If
        End Try
    End Sub


    Private Sub Button1_Click(ByVal sender As System.Object, _
                ByVal e As System.EventArgs) _
                Handles Button1.Click

        'クローズしないぜ
        CloseTest(CInt(TextBox1.Text), False)

    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, _
                ByVal e As System.EventArgs) _
                Handles Button2.Click

        'クローズするか。
        CloseTest(CInt(TextBox1.Text), True)

    End Sub
End Class


DataReader Closeテスト

 

見てもらうとわかりますが、1回目と3回目は「DataReaderをCloseするよー」ボタンを押した結果です。
それに対して2回目、4回目は「DataReaderをCloseしないよ」ボタンを押した結果です。

ものの見事にエラーが出ちゃいましたぁ....
必ずCloseしましょうね。

 

と言うわけで、プログラムにおける実験は一旦終了しますが、「なんでそうなるの?」とか、「どうしたらいいの?」などを追求したい方は、色んな所にテキストがありますが、@マークITのこの記事がわかりやすいので見てみてくださいね。

 

(2009.06.05) End of Text