DataReader не закрывается при закрытии соединения, последствия?

например, у меня есть этот код:

Sub Month()
    Dim Conn As New Data.OracleClient.OracleConnection
    Conn.Open()
    Try

        Dim Cmd As New Data.OracleClient.OracleCommand
        With Cmd
            .Connection = Conn
            .CommandType = Data.CommandType.Text
            .CommandText = "SELECT * FROM MONTH"
        End With
        Dim datareader As Data.OracleClient.OracleDataReader = Cmd.ExecuteReader
        While datareader.Read
            Response.Write(datareader(0))
        End While
    Catch ex As Exception
        Throw ex
    Finally
        Conn.Close()
    End Try
End Sub

Что произойдет с устройством чтения данных, когда соединение будет закрыто ( Conn.close )

Будет ли освобожден курсор, используемый устройством чтения данных? или останется открытым?

Если курсор, который используется устройством чтения данных, все еще открыт, когда он будет автоматически закрыт? или я должен просто закрыть его вручную?

Не вызовет ли это ужасный «ORA-01000: превышено максимальное количество открытых курсоров»?

заранее спасибо


person Garry -    schedule 31.05.2011    source источник
comment
использовать с командой для vb.net и использовать для C #, это автоматически закроет соединение dr, не закрытие которого сопряжено с огромным риском для производительности.   -  person Deepesh    schedule 31.05.2011
comment
@ user751975 - Использование в VB.Net не то же самое, что использование в C#. В VB.Net это называется Использование   -  person Chris Dunaway    schedule 31.05.2011
comment
2014 год, и у меня тот же вопрос с Oracle. Вы нашли ответ? Я получаю это ужасное сообщение, но все мои соединения создаются с помощью оператора using (что то же самое, что и try..finally), и я не знаю, где искать ответ.   -  person Fernando    schedule 05.06.2014


Ответы (4)


Вы должны создать объекты в блоке использования, чтобы они были правильно расположены:

Using Conn As New Data.SqlClient.SqlConnection
    Conn.Open()

    Dim Cmd As New Data.SqlClient.SqlCommand
    With Cmd
        .Connection = Conn
        .CommandType = Data.CommandType.Text
        .CommandText = "SELECT * FROM MONTH"
    End With

    Using datareader As Data.SqlClient.SqlDataReader = Cmd.ExecuteReader()
        While datareader.Read()
            Response.Write(datareader(0))
        End While
    End Using
End Using

Нет необходимости вызывать Close ни для соединения, ни для устройства чтения данных.

person Chris Dunaway    schedule 31.05.2011

CommandBehavior.CloseConnection

Когда вы передаете вышеуказанные значения в качестве аргумента для ExecuteReader 1. нет необходимости закрывать соединение явно, соединение закрывается, когда вы закрываете свой ридер.

проверьте полный пост: http://pranayamr.blogspot.com/2010/11/executereader-with-commanbehavior.html

person Pranay Rana    schedule 31.05.2011
comment
да, это правда, но что произойдет, если вы закроете только соединение, но не сам ридер. - person Garry -; 31.05.2011
comment
@Garry - ридер всегда использует живое соединение для чтения данных из базы данных ... если вы закрываете соединение, а затем пытаетесь прочитать его с помощью ридера, он выдает excetpion, соединение закрывается - person Pranay Rana; 31.05.2011
comment
да, то есть если вы попытаетесь получить к нему доступ, когда соединение закрыто, будет ли закрыт также курсор, используемый читателем? или он застрянет на сервере оракула и приведет к превышению максимального курсора - person Garry -; 31.05.2011
comment
@Garry - проверьте этот ответ: stackoverflow.com/questions/ 2519379/ - person Pranay Rana; 31.05.2011
comment
уже читал это раньше, но это не объясняет, что произойдет с курсором или другими моими вопросами - person Garry -; 31.05.2011

Просто создайте новый объект чтения данных после его закрытия

private void button2_Click(object sender, EventArgs e)
    {
        //SqlConnection cn1 = new SqlConnection();
        cn.ConnectionString = "server = .\\SQLEXPRESS ; database=store ; integrated security = true  ";
        SqlCommand cm = new SqlCommand("select * from emp", cn);
        cn.Open();
        SqlDataReader dr = cm.ExecuteReader();
        DataTable dt = new DataTable();
        dt.Load(dr);
        dataGridView1.DataSource = dt.DefaultView ;
        //SqlCommand cm3 = new SqlCommand("select * from emp", cn1);
        SqlDataReader dr1 = cm.ExecuteReader();
        listBox1.Items.Clear();
        while (dr1.Read())
        {
            //listBox1.Items.Add(dr.GetString(2));
            listBox1.Items.Add(dr1["name"]);

        }
        cn.Close();
    }
person Awadallah    schedule 23.10.2012

Почему бы вам явно не закрыть читалку вот так.

считыватель данных.Закрыть()

Dim Conn As New Data.SqlClient.SqlConnection
Conn.Open()
Try

    Dim Cmd As New Data.SqlClient.SqlCommand
    With Cmd
        .Connection = Conn
        .CommandType = Data.CommandType.Text
        .CommandText = "SELECT * FROM MONTH"
    End With
    Dim datareader As Data.SqlClient.SqlDataReader = Cmd.ExecuteReader
    While datareader.Read
        Response.Write(datareader(0))
    End While
    datareader.Close()
Catch ex As Exception
    Throw ex
Finally
    Conn.Close()
End Try
person Sreekumar P    schedule 31.05.2011
comment
вот что я пытаюсь выяснить, почему мы должны закрывать считыватель данных, когда само соединение будет закрыто в конечном итоге, я пытаюсь выяснить, что может произойти, если считыватель данных используется как мой код - person Garry -; 31.05.2011
comment
Вы должны создавать SqlConnection и DataReader в блоке Using, так как они оба реализуют IDisposable. Таким образом, они будут правильно утилизированы, когда вы закончите с ними. - person Chris Dunaway; 31.05.2011