Отправленный запрос SQL C # INSERT фактически не добавляет никаких новых записей в таблицу

#c# #sql

#c# #sql

Вопрос:

В настоящее время я использую C # для выполнения запросов к базе данных SQL. Запрос SELECT работает нормально, а запрос INSERT — нет.

Я запустил тот же запрос из самого SQL Server Manager, и он работает нормально, но когда я отправляю его с C # (используя страницу ASP с текстовыми полями для указания отправляемых значений для столбцов), страница просто обновляется и не показывает никаких ошибок.

Тот факт, что запрос SELECT работает, говорит мне, что сервер подключается нормально и что это не проблема. Я использовал точки останова в коде C #, чтобы проверить, правильно ли переменные отправляются из текстовых полей, и они должны быть.

Есть идеи, что происходит не так?

Вот код:

   protected void SendMyData_OnClick(object sender, EventArgs e)
    {
        //(NO RECORD SET IS NEEDED IN THIS FUNCTION SEEING AS HOW WE'RE NOT FETCHING ANYTHING) 

         SqlConnection conServer = new SqlConnection(CDatabase.ConnectionString());

        // Database variables
        string Track_Name   = TextBox8.Text;

        string Track_No     = TextBox10.Text;
        long TN             = Convert.ToInt64(Track_No);

        string Artist_ID    = TextBox11.Text;
        long ArtID          = Convert.ToInt64(Artist_ID);

        string Album_ID     = TextBox12.Text;
        long AlbID          = Convert.ToInt64(Album_ID);
        //SUB THESE INTO THE SQL QUERY 

        try
        {
            string qrySQL = string.Format("INSERT INTO Tracks ([Track_Name],[Track_No],[Artist_ID],[Album_ID]) VALUES ({0}, {1}, {2}, {3})", Track_Name, TN, ArtID, AlbID);

            //This is the string Used to send (Note the NonReturn(As we aren't fetching anything) : " conServer.Open();CDatabase.ExecuteNonReturnQuery(qrySQL);"

            conServer.Open();
            //(NO RECORD SET IS NEEDED IN THIS FUNCTION SEEING AS HOW WE'RE NOT FETCHING ANYTHING) 
            CDatabase.ExecuteNonReturnQuery(qrySQL);
        }
        catch
        {
        }

        finally
        {
           conServer.Close();
        }
  

Комментарии:

1. Это курсовая работа? Это определенно выглядит так: P

Ответ №1:

Что ж, здесь есть как минимум две серьезные ошибки:

  • Вы встраиваете значения непосредственно в свой SQL. Добро пожаловать в страну атак с использованием SQL-инъекций. Не делайте этого.Вместо этого используйте параметризованный SQL, указав значения отдельно. (См SqlCommand.Parameters . Документы для примера.)
  • Вы перехватываете все исключения и просто проглатываете их без регистрации. Вполне возможно, что этот код выдает исключение, которое точно объясняет, что происходит не так, но вы никогда не узнаете, потому что ваш код имеет свои метафорические пальцы в ушах.

Я предполагаю, что он выдает исключение из-за того, что имя дорожки не параметризовано и не заключено в кавычки — у вас есть произвольная строка в середине вашего SQL.

Перехват всех исключений почти всегда неверен, и особенно на этом уровне. Обычно вы должны разрешать исключениям распространяться на более высокие уровни, где у вас вполне может быть общий блок верхнего уровня для «что-то пошло не так с запросом, и мы не хотим выводить из строя весь сервер» — ASP.NET конечно, предоставляет вам один из них и позволяетукажите, как следует обрабатывать ошибки.

Кроме того, вместо явного закрытия SQL-соединения я бы обернул все это в using инструкцию (и только после анализа входных данных).

 using (SqlConnection con = new SqlConnection(...))
{
    con.Open();
    using (SqlCommand command = ...)
    {
        // Execute the command
    }
}
  

Наконец, ваше именование переменных непоследовательно — иногда вы используете, camelCase а иногда используете PascalCase . Честно говоря, необычно видеть переменные в оболочке Pascal — аналогично переменные с подчеркиванием. Сокращение «Исполнитель» и «Альбом» до «Art» и «Alb» также делает код менее читаемым.

Комментарии:

1. Спасибо. Я избавился от пустого улова и создал файл трассировки, и теперь я получаю эту ошибку: «26/10/2011 10:01:22: Исключение, добавляющее учетную запись. Имя «track1″ в этом контексте недопустимо. Допустимыми выражениями являются константы, постоянные выражения и (в некоторых контекстах) переменные. Имена столбцов не разрешены. » Я предполагаю, что это как-то связано с именем дорожки, не заключенным в кавычки?

2. @Adam: Да. Но не исправляйте это, добавляя кавычки в строку вашего формата — исправьте это с помощью параметризованного оператора SQL.

3. БОЛЬШОЕ СПАСИБО! Я добавил » вокруг {0}, поскольку это символы, которые мы отправляем, а не строка. Сейчас я работаю над тем, чтобы перевести его в параметризованный SQL. Если кому-то интересно, я делаю это, чтобы изучить C # -> SQL материал, который я позже буду использовать для расширенного проекта. (Кстати, я студент 13-го курса в Великобритании — старший в средней школе для вас, американцев)

4. Вы вводите значения, потому что вы создаете динамическую строку с помощью string . Format(…, arg1, …);. Что, если arg1 будет содержать сам оператор sql? Тогда кто-то ввел бы sql в ваш запрос, и он будет выполнен

5. @Adam: Подумайте, что произойдет, если кто-то введет имя дорожки IGNORE', 0, 0, 0); DROP TABLE Tracks; // . Как будет выглядеть ваша инструкция SQL в этот момент, и вы действительно хотите ее выполнить? Другими словами, вы делаете эквивалент SQL, позволяя людям писать код C # для выполнения непосредственно на вашем веб-сервере. Не очень хорошая идея.

Ответ №2:

Страница обновится, потому что у вас есть пустое предложение catch. Поэтому, если есть ошибка, вы поймаете ее и проглотите ошибку.

Попробуйте удалить предложение catch или добавить в него новый «throw», который вернет исключение

Ответ №3:

Ваш код выдает исключение, которое вы не видите из-за пустого catch. Ваши текстовые значения не имеют ‘ вокруг них, что приводит к сбою SQL. КАК упоминалось другими, вы должны использовать параметризованный SQL, который не только устранит эту проблему, но и защитит вас (r) от атак SQL-инъекций

Ответ №4:

Будет работать следующее:

 SqlConnection sqlConnection = new SqlConnection(ConnectionString);
string qrySQL = string.Format("INSERT INTO Tracks ([Track_Name],[Track_No],[Artist_ID],[Album_ID]) VALUES ({0}, {1}, {2}, {3})", Track_Name, TN, ArtID, AlbID);
SqlCommand sqlCommand = new SqlCommand(qrySQL, sqlConnection);
sqlConnection.Open();
sqlCommand.ExecuteNonQuery();
  

Вам было бы лучше использовать параметры, чтобы избежать проблем с типами данных и проблемами безопасности.

 string qrySQL = "INSERT INTO Tracks ([Track_Name],[Track_No],[Artist_ID],[Album_ID]) VALUES (@Track_Name,@Track_No,@Artist_ID,@Album_ID)";
sqlCommand.Parameters.AddWithValue("@Track_Name", "Value");
  

и так далее..

Комментарии:

1. Я не думаю, что это сработает, потому что запрос завершится ошибкой — значение для Track_Name должно быть заключено в кавычки.

Ответ №5:

Это курсовая работа? Это определенно выглядит так: P

Кроме того, квадратные скобки вокруг параметров — это SQL Server? Я не видел, чтобы это было написано так раньше. Я бы подумал, что это просто «ВСТАВИТЬ В дорожки (Track_Name, Track_Number и т. Д… Попробуйте распечатать исключение… например

 catch Exception e{
print e
}
  

Итак, вы можете видеть, что происходит

Не уверен в точном синтаксисе

Ответ №6:

Разве первое значение (Track_Name) не должно быть заключено в кавычки, поскольку это строка?

 string qrySQL = string.Format("INSERT INTO Tracks ([Track_Name],[Track_No],[Artist_ID],[Album_ID]) VALUES ('{0}', {1}, {2}, {3})", Track_Name, TN, ArtID, AlbID);
  

ОТРЕДАКТИРОВАНО ДЛЯ ДОБАВЛЕНИЯ

Как говорили другие (в своих лучших и более полных ответах, IMO), вы широко открыты для атак SQL-инъекций с кодом как есть — единственное, что сделал мой ответ, это исправить запрос, чтобы он действительно вставлялся.

Конечно, как указал Джон Скит, вам нужно выполнять обработанный SQL. Я ценю принятый ответ, но ответ I Jon был лучшим общим ответом, и вы действительно должны согласиться с тем, что другие пользователи могут столкнуться с этим вопросом в своих собственных поисках и должны иметь наиболее точный и полный ответ (IMO).

Комментарии:

1. и, очевидно, мы также хотим установить значение TextBox8.Text в ',0,0,0);TRUNCATE TABLE Tracks;DROP TABLE Tracks;SELECT 1 WHERE 1 IN ('0

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

3. Вау … -1 в старом ответе, где я даже отредактировал его, чтобы указать, что ответ Джона Скита был правильным. Неважно.