nar86 Ответов: 1

С этой командой уже связан открытый datareader, который должен быть закрыт в первую очередь. С#


с этой командой уже связан открытый datareader, который должен быть закрыт в первую очередь



Мой код выглядит следующим образом

protected void btnsubmit_Click(object sender, EventArgs e)
        {
 try
            {
                String strConnString = ConfigurationManager.ConnectionStrings["IvcSpiderDBConnectionStrings"].ConnectionString;
                SqlConnection con = new SqlConnection(strConnString);
                con.Open();

                SqlCommand check_User_Name = new SqlCommand("SELECT * FROM [master].[settings] WHERE ([year] = @year) and ([batch] = @batch) ", con);

                check_User_Name.Parameters.AddWithValue("@year", txtyear.Text);
                check_User_Name.Parameters.AddWithValue("@batch", txtbatch.Text);
                SqlDataReader dr = check_User_Name.ExecuteReader();

                if (dr.HasRows)
                {
                    ScriptManager.RegisterStartupScript(this, GetType(), "showalert", "alert('Please update year or batch and then click update');", true);
                    return;
                }
                else
                { 
                    SqlCommand cmd = new SqlCommand("UPDATE [master].[settings] set year = '" + txtyear.Text.ToString() + "',batch = '" + txtbatch.Text.ToString() + "'", con);
                    cmd.ExecuteNonQuery();
                    ScriptManager.RegisterStartupScript(this, GetType(), "showalert", "alert('Records updated ');", true);
                    con.Close();
                    BindData();
                }
                   dr.Close();
            }
            catch (Exception ex)
            {
                Logger log = new Logger();
                log.WriteToErrorLog("Error while updating data", "EXCEPTION", ex.Message.ToString(), "", "");
            }
}


После обновления запись в текстовом поле показывает ниже ошибку следующим образом

с этой командой уже связан открытый datareader, который должен быть закрыт в первую очередь.

как решить эту ошибку.

Что я уже пробовал:

с этой командой уже связан открытый datareader, который должен быть закрыт в первую очередь



Мой код выглядит следующим образом

protected void btnsubmit_Click(object sender, EventArgs e)
        {
 try
            {
                String strConnString = ConfigurationManager.ConnectionStrings["IvcSpiderDBConnectionStrings"].ConnectionString;
                SqlConnection con = new SqlConnection(strConnString);
                con.Open();

                SqlCommand check_User_Name = new SqlCommand("SELECT * FROM [master].[settings] WHERE ([year] = @year) and ([batch] = @batch) ", con);

                check_User_Name.Parameters.AddWithValue("@year", txtyear.Text);
                check_User_Name.Parameters.AddWithValue("@batch", txtbatch.Text);
                SqlDataReader dr = check_User_Name.ExecuteReader();

                if (dr.HasRows)
                {
                    ScriptManager.RegisterStartupScript(this, GetType(), "showalert", "alert('Please update year or batch and then click update');", true);
                    return;
                }
                else
                { 
                    SqlCommand cmd = new SqlCommand("UPDATE [master].[settings] set year = '" + txtyear.Text.ToString() + "',batch = '" + txtbatch.Text.ToString() + "'", con);
                    cmd.ExecuteNonQuery();
                    ScriptManager.RegisterStartupScript(this, GetType(), "showalert", "alert('Records updated ');", true);
                    con.Close();
                    BindData();
                }
                   dr.Close();
            }
            catch (Exception ex)
            {
                Logger log = new Logger();
                log.WriteToErrorLog("Error while updating data", "EXCEPTION", ex.Message.ToString(), "", "");
            }
}

После обновления запись в текстовом поле показывает ниже ошибку следующим образом

с этой командой уже связан открытый datareader, который должен быть закрыт в первую очередь.

как решить эту ошибку.

1 Ответов

Рейтинг:
0

OriginalGriff

Сообщение об ошибке довольно явное:

There is already an open datareader associated with this command which must be closed first.
У вас есть открытый DataReader на этом соединении, который "держит" команду до тех пор, пока она не будет закрыта. До тех пор вы не можете ничего сделать с одним и тем же объектом соединения.

Самое простое решение-всегда использовать using блокируйте объекты подключения, команды и адаптера таким образом, чтобы они автоматически закрывались и удалялись, когда выходят за пределы области действия:
using (SqlCommand check_User_Name = new SqlCommand("SELECT * FROM [master].[settings] WHERE ([year] = @year) and ([batch] = @batch) ", con))
    {
    check_User_Name.Parameters.AddWithValue("@year", txtyear.Text);
    check_User_Name.Parameters.AddWithValue("@batch", txtbatch.Text);
    using (SqlDataReader dr = check_User_Name.ExecuteReader())
       {
        if (dr.HasRows)
            {
            ScriptManager.RegisterStartupScript(this, GetType(), "showalert", "alert('Please update year or batch and then click update');", true);
            return;
            }
        }
    }
using (SqlCommand cmd = new SqlCommand("...", con))
    {
    cmd.ExecuteNonQuery();
    ...
    }


Но... У тебя есть и другие проблемы.

#Вы знаете о параметризованных запросах, так почему же вы вдруг оставляете себя широко открытыми для SQL-инъекций? Никогда не объединяйте строки для построения команды SQL. Это оставляет вас широко открытыми для случайной или преднамеренной атаки SQL-инъекции, которая может уничтожить всю вашу базу данных. Вместо этого всегда используйте параметризованные запросы.

Когда вы объединяете строки, вы вызываете проблемы, потому что SQL получает такие команды, как:
SELECT * FROM MyTable WHERE StreetAddress = 'Baker's Wood'
Цитата, добавленная пользователем, завершает строку в том, что касается SQL, и вы получаете проблемы. Но могло быть и хуже. Если я приду и наберу вместо этого: "x';DROP TABLE MyTable;--", то SQL получит совсем другую команду:
SELECT * FROM MyTable WHERE StreetAddress = 'x';DROP TABLE MyTable;--'
Которые SQL видит как три отдельные команды:
SELECT * FROM MyTable WHERE StreetAddress = 'x';
Совершенно правильный выбор
DROP TABLE MyTable;
Вполне допустимая команда "удалить таблицу"
--'
А все остальное-это комментарии.
Так оно и происходит: выбирает любые совпадающие строки, удаляет таблицу из базы данных и игнорирует все остальное.

Поэтому всегда используйте параметризованные запросы! Или будьте готовы часто восстанавливать свою БД из резервной копии. Вы ведь регулярно делаете резервные копии, не так ли?

И если вы только хотите знать, существуют ли какие-либо строки, зачем вообще использовать DataReader? Воспользуйся
SELECT COUNT(*) FROM ...
вместо запроса SELECT, и позвонить executescalar так, а не -, которая возвращает число, а не на фактических данных и является гораздо более эффективным.