Tshumore Ответов: 2

Как сделать вставку только для столбцов с нулевым значением


I have a routine that checks for rows with NULL values, for a specified column. For each instance of a NULL value found i would like to insert values in the same using some criteria. Im getting a "There is already an open DataReader associated with this Command which must be closed first" exception. This is thrown when control flow has already surpassed the first INSERT condition.. but however when i check the table nothing has been committed. I was expecting to see data for the first condition despite of the exception. I need help on 1) if im doing the NULL check as well as insert correctly. For now i can observe that nothing is being committed. 2) I have checked and still cant see any datareader i have left unclosed.
Мой код:
using (SqlConnection conn = new SqlConnection(Helpers.DatabaseConnect))
           {
               SqlCommand cmd = new SqlCommand("SELECT DISTINCT transdetail_id FROM Tdata WHERE period_name='" + (reportingPeriod) + "' AND agent_shortname IS NULL", conn);

               conn.Open();
               SqlDataReader dr = cmd.ExecuteReader();
               while (dr.Read())
               {

                   Models.FileUpload.Mapping mapping = new Models.FileUpload.Mapping();

                   mapping.TransactionDetailId = Convert.ToString(dr["transdetail_id"]);

                   using (SqlConnection conn1 = new SqlConnection(Helpers.DatabaseConnect))
                   {

                       SqlCommand cmd1 = new SqlCommand("SELECT company_code FROM TData WHERE transdetail_id='" + Convert.ToString(mapping.TransactionDetailId) + "'", conn1);

                       conn1.Open();
                       SqlDataReader dr1 = cmd1.ExecuteReader();

                        if (dr1.Read() == true)
                        {

                           mapping.companycode = Convert.ToString(dr1["company_code"]);

                       if (mapping.companycode == Harare)
                       {
                           using (SqlConnection connp = new SqlConnection(Helpers.DatabaseConnect))
                           {

                               cmd.CommandText = @"INSERT INTO TData(agent_shortname) VALUES(@agentanalysiscode) WHERE transdetail_id='" + Convert.ToString(mapping.TransactionDetailId) + "'";
                               cmd.Parameters.AddWithValue("@agentanalysiscode", HreCode);
                               try
                               {
                                   connp.Open();
                                   cmd.ExecuteNonQuery();
                               }
                               catch (SqlException e)
                               {
                                   ViewBag.ErrorMessage = "Processing error !";
                                   return View();
                               }
                               connp.Close();
                           }
                       }

                      //else if (mapping.companycode == Bulawayo)
                   //insert different value based on company_code i.e Bulawayo
                       }

                       conn1.Close();
                   }

               }
              conn.Close();

           }


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

Когда я выполняю SQL запрос
SELECT        transdetail_id
FROM            TData
WHERE        (agent_shortname IS NULL)
в SSMS я могу получить transdetail_id для нулевых столбцов:

Просто для ясности все мои колонки-это nvarchar(MAX). Любая помощь в том, что я могу упустить.

Richard Deeming

"SELECT DISTINCT transdetail_id FROM Tdata WHERE period_name='" + (reportingPeriod) + "' AND agent_shortname IS NULL"


Не делай этого так!

Ваш код уязвим для SQL-инъекция[^]. НИКОГДА используйте конкатенацию строк для построения SQL-запроса. ВСЕГДА используйте параметризованный запрос.

Все, что вы хотели знать о SQL-инъекции (но боялись спросить) | Трой Хант[^]
Как я могу объяснить SQL-инъекцию без технического жаргона? | Обмен Стеками Информационной Безопасности[^]
Шпаргалка по параметризации запросов | OWASP[^]

2 Ответов

Рейтинг:
2

dbrenth

У вас много проблем с вашим кодом:

1. Почему вы продолжаете воссоздавать один и тот же объект SqlConnection? Просто используйте один и тот же снова и снова. Вы просто тратите впустую память и добавляете нагрузку на свой SQL-сервер.

2. вы переопределяете CommandText переменной cmd, когда cmd открыт для чтения, и в настоящее время индексируете его в своем операторе while. Вы должны просто создать новую переменную для этой третьей строки SQL. (Вот откуда исходит ваша ошибка)

3. Ваш оператор Insert имеет недопустимый синтаксис. Вы хотели использовать инструкцию UPDATE?

Надеюсь, что исправление этих ошибок поставит вас на правильный путь.

Брент


Tshumore

Спасибо, ребята.. При переходе на инструкцию UPDATE я все еще не могу вставить в столбцы с нулевыми значениями..Что я упускаю из виду,
используя (sqlconnection с соед = новый объект sqlconnection(помощники.DatabaseConnect))
{
Модели.Загрузка файлов.Mapping mapping = новые модели.Загрузка файлов.Отображение();

Команда sqlcommand cmd и = новая команда sqlcommand("выбрать различные transdetail_id от TData где period_name='" + преобразование.ToString(reportingPeriod) + "' AND agent_shortname IS NULL", conn);

Коннектикут.Открыть();
SqlDataReader dr = cmd.Метода executereader();
если (др.Прочитать() == истина)
{
отображение.TransactionDetailId = Конвертировать.Метод toString(д-р["transdetail_id"]);
}

остальное, если (д-р.Прочитать() == Ложь)
{
отображение.TransactionDetailId = строка.Пустой;
}
Коннектикут.Закрывать();

SqlCommand cmd1 = new SqlCommand("SELECT company_code FROM TData WHERE transdetail_id='" + Convert.ToString(отображение.TransactionDetailId) + "'", conn);
Коннектикут.Открыть();
SqlDataReader dr1 = cmd1.Метода executereader();
если (ДР1.Прочитать() == истина)
{

mapping.companycode = конвертировать.Метод toString(ДР1["company_code"]);
}
остальное, если (д-р.Прочитать() == Ложь)
{
mapping.companycode = строка.Пустой;
}

Коннектикут.Закрывать();
}
using (SqlConnection conn1 = new SqlConnection(Helpers.DatabaseConnect))
{
Модели.Загрузка файлов.Mapping mapping = новые модели.Загрузка файлов.Отображение();

если (отображение.companycode == Хараре)
{
String query = "UPDATE TData SET agent_shortname =@agentanalysiscode WHERE company_code=@companycode";
Sqlcommand, который cmd3 = новый sqlcommand, который(запрос, conn1);
cmd3.параметры.AddWithValue ("@company_code", Convert.Метод toString(картирование.companycode));
cmd3.параметры.AddWithValue("@agentanalysiscode", HreCode);
пробовать
{
conn1.Открыть();
cmd3.Метод executenonquery();
}
catch (SqlException e)
{
Видовой мешок.ErrorMessage = "ошибка обработки !";
возвращение смотреть();
}
conn1.Закрывать();
}

else if (mapping.companycode == Булавайо)
{

String query = "UPDATE TData SET agent_shortname =@agentanalysiscode WHERE company_code=@companycode";
Sqlcommand, который cmd3 = новый sqlcommand, который(запрос, conn1);
cmd3.параметры.AddWithValue ("@company_code", Convert.Метод toString(картирование.companycode));
cmd3.параметры.AddWithValue("@agentanalysiscode", ByoCode);
пробовать
{
conn1.Открыть();
cmd3.Метод executenonquery();
}
catch (SqlException e)
{
Видовой мешок.ErrorMessage = "ошибка обработки !";
возвращение смотреть();
}
conn1.Закрывать();
}


}

dbrenth

Если это точная копия паста то вам нужно исправить имена ваших параметров:

String query = "UPDATE TData SET agent_shortname =@agentanalysiscode WHERE company_code=@companycode";
Sqlcommand, который cmd3 = новый sqlcommand, который(запрос, conn1);
cmd3.параметры.AddWithValue ("@company_code", Convert.Метод toString(картирование.companycode));

В первой строке это @companycode, а в последней строке - @company_code
В обоих местах вашего кода. Они должны совпадать.

dbrenth

Кроме того, не продолжайте закрывать и открывать соединение. В конце инструкции using соединение будет автоматически закрыто. Он может оставаться открытым на протяжении всего оператора using.

Рейтинг:
1

RickZeeland

Я думаю, что вам нужно изменить команду INSERT на команду UPDATE.
Пример здесь: Инструкция SQL UPDATE | с несколькими столбцами[^]