использовать один и тот же экземпляр SQLCommand более одного раза в одном и том же коде для более чем одного запроса?

У меня есть вопрос об использовании, почему я не могу использовать один и тот же экземпляр SQLCommand более одного раза в одном и том же коде?

Я попробовал код здесь, и он хорошо работает для gridview, но когда я изменил запрос с помощью метода cmd.CommandText(), он продолжает говорить:

С этой командой уже связан открытый DataReader, который необходимо сначала закрыть.

Это код:

string cs = ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString;
SqlConnection con = new SqlConnection(cs);

try
{
    SqlCommand cmd = new SqlCommand();
    cmd.Connection = con;
    con.Open();
    cmd.CommandText = "Select top 10 FirstName, LastName, Address, City, State from Customers";

    GridView1.DataSource = cmd.ExecuteReader(); 
    GridView1.DataBind();


    cmd.CommandText = "SELECT TOP 10 COUNT(CreditLimit) FROM Customers";
    int total = (int)cmd.ExecuteScalar();
    TotalCreditLble.Text = "The total Credit :" + total.ToString();

}
catch(Exception exp)
{
    Response.Write(exp.Message);
}
finally
{
    con.Close();
}

person Max Byan    schedule 14.11.2013    source источник


Ответы (3)


Проблема в том, что вы используете объект SqlCommand для создания DataReader с помощью команды command.ExecuteReader(). Пока он открыт, вы не можете повторно использовать команду.

Это должно работать:

using (var reader = cmd.ExecuteReader())
{
    GridView1.DataSource = reader;
    GridView1.DataBind();
}
//now the DataReader is closed/disposed and can re-use command
cmd.CommandText = "SELECT TOP 10 COUNT(CreditLimit) FROM Customers";
int total = (int)cmd.ExecuteScalar();
TotalCreditLble.Text = "The total Credit :" + total.ToString();
person Sven Grosen    schedule 14.11.2013

С этой командой уже связан открытый DataReader, который необходимо сначала закрыть.

Это та самая причина, по которой вы не разделяете команду. Где-то в вашем коде вы сделали это:

cmd.ExecuteReader();

но вы не использовали оператор using вокруг команды, потому что хотели поделиться им. Вы не можете этого сделать. Видите, ExecuteReader оставляет соединение с сервером открытым, пока вы читаете по одной строке за раз; однако эта команда сейчас заблокирована, потому что на данный момент она сохраняет состояние. Правильный подход всегда таков:

using (SqlConnection c = new SqlConnection(cString))
{
    using (SqlCommand cmd = new SqlCommand(sql, c))
    {
        // inside of here you can use ExecuteReader
        using (SqlDataReader rdr = cmd.ExecuteReader())
        {
            // use the reader
        }
    }
}

Это неуправляемые ресурсы, и с ними нужно обращаться осторожно. Вот почему обертывание их using является обязательным.

Не делитесь этими объектами. Создавайте их, открывайте, используйте и утилизируйте.

Используя using, вам никогда не придется беспокоиться о закрытии и удалении этих объектов.


Ваш код, написанный немного по-другому:

var cs = ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString;
var gridSql = "Select top 10 FirstName, LastName, Address, City, State from Customers";
var cntSql = "SELECT TOP 10 COUNT(CreditLimit) FROM Customers";

using (SqlConnection con = new SqlConnection(cs))
{
    con.Open();

    try
    {
        using (SqlCommand cmd = new SqlCommand(gridSql, con))
        {
            GridView1.DataSource = cmd.ExecuteReader(); 
            GridView1.DataBind();
        }

        using (SqlCommand cmd = new SqlCommand(cntSql, con))
        {
            int total = (int)cmd.ExecuteScalar();
            TotalCreditLble.Text = "The total Credit :" + total.ToString();
        }
    }
    catch(Exception exp)
    {
        Response.Write(exp.Message);
    }
}
person Mike Perrenoud    schedule 14.11.2013
comment
Я согласен с вашим мнением о том, что нельзя повторно использовать команды/соединения, поскольку это может только доставить вам неприятности. - person Sven Grosen; 14.11.2013

Спасибо, ребята, но для парней, которые говорили об использовании блока! почему этот код работает нормально, что я видел на примере видео! Это то же самое, используя один и тот же экземпляр SqlCommand и передавая разные запросы с помощью метода CommanText с тем же экземпляром SqlCommand, и он выполняется просто отлично, это код:

using (SqlConnection con = new SqlConnection(cs))
{
   SqlCommand cmd = new SqlCommand();
   cmd.Connection = con;
   con.Open();

   cmd.CommandText = "Delete from tbleProduct where ProductID= 4";
   int TotalRowsAffected = cmd.ExecuteNonQuery();
   Response.Write("Total rows affected :" + TotalRowsAffected );

   cmd.CommandText = "Insert into tbleProduct values (4, 'Calculator', 100, 230)";
   TotalRowsAffected = cmd.ExecuteNonQuery();
   Response.Write("Total rows affected :" + TotalRowsAffected );


   cmd.CommandText = "ypdate tbleProduct set QtyAvailbe = 234 where ProductID = 2";
   TotalRowsAffected = cmd.ExecuteNonQuery();
   Response.Write("Total rows affected :" + TotalRowsAffected );

 }
person Max Byan    schedule 14.11.2013