.ExecuteNonQuery() ошибка sql asp.net

Я впервые работаю с sql и asp.net. Я работаю над несколькими примерами, чтобы убедиться, что у меня есть все необходимые основы. Я ходил по учебнику, и там, где все должно работать нормально, я получаю ошибку .ExecuteNonQuery(). Исключение SqlException не было обработано пользовательским кодом // Неверный синтаксис рядом с ключевым словом «Таблица».

Если у вас есть какие-либо указатели, дайте мне знать. Я работал с учебником дважды, я уверен, что делаю что-то не так. -Спасибо

.CS-код:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.SqlClient;
using System.Configuration;

namespace WebSite
{
public partial class _default : System.Web.UI.Page
{
    SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);

    protected void Page_Load(object sender, EventArgs e)
    {
        con.Open();
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        SqlCommand cmd = new SqlCommand("insert into Table values('" + txtfName.Text + "','" + txtlName.Text + "','" + txtpNumber.Text + "')", con);
        cmd.ExecuteNonQuery();
        con.Close();
        Label1.Visible = true;
        Label1.Text = "Your DATA has been submitted";
        txtpNumber.Text = "";
        txtlName.Text = "";
        txtfName.Text = "";
    }
  }
}

.aspx-файл:

<form id="form1" runat="server">
<div class="auto-style1">

    <strong>Insert data into Database<br />
    <br />
    </strong>

</div>
    <table align="center" class="auto-style2">
        <tr>
            <td class="auto-style3">First Name:</td>
            <td class="auto-style4">
                <asp:TextBox ID="txtfName" runat="server" Width="250px"></asp:TextBox>
            </td>
        </tr>
        <tr>
            <td class="auto-style3">Last Name:</td>
            <td class="auto-style4">
                <asp:TextBox ID="txtlName" runat="server" Width="250px"></asp:TextBox>
            </td>
        </tr>
        <tr>
            <td class="auto-style3">Phone Number:</td>
            <td class="auto-style4">
                <asp:TextBox ID="txtpNumber" runat="server" Width="250px"></asp:TextBox>
            </td>
        </tr>
        <tr>
            <td class="auto-style3">&nbsp;</td>
            <td class="auto-style4">
                <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Submit" Width="150px" />
            </td>
        </tr>
    </table>
    <br />
    <br />
    <asp:Label ID="Label1" runat="server" ForeColor="#663300" style="text-align: center" Visible="False"></asp:Label>
    <br />
    <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:ConnectionString %>" SelectCommand="SELECT * FROM [Table]"></asp:SqlDataSource>
</form>

База данных SQL:

CREATE TABLE [dbo].[Table] (
[Id]      INT          IDENTITY (1, 1) NOT NULL,
[fName]   VARCHAR (50) NOT NULL,
[lName]   VARCHAR (50) NOT NULL,
[pNumber] VARCHAR (50) NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
);

person Sean Robbins    schedule 19.05.2013    source источник
comment
Предупреждение о SQL-инъекциях — следует не объединяйте операторы SQL вместе — вместо этого используйте параметризованные запросы, чтобы избежать внедрения SQL.   -  person marc_s    schedule 20.05.2013


Ответы (4)


Обычно это сообщение об ошибке вызвано наличием одиночной кавычки в текстовых полях ввода или использованием зарезервированного ключевого слова. Обе проблемы присутствуют в вашем запросе. Слово TABLE является зарезервированным ключевым словом для SQL Server, поэтому заключать его в квадратные скобки, а при возможном наличии во входном тексте одинарной кавычки правильным подходом является использование параметризованный запрос, подобный этому

SqlCommand cmd = new SqlCommand("insert into [Table] values(@fnam, @lnam, @pNum)", con);
cmd.Parameters.AddWithValue("@fnam", txtfName.Text );
cmd.Parameters.AddWithValue("@lnam", txtlName.Text );
cmd.Parameters.AddWithValue("@pNum", txtpNumber.Text);
cmd.ExecuteNonQuery();

При таком подходе вы переносите работу по разбору входного текста на код фреймворка и избегаете проблем с разбором текста и Sql Injection

Кроме того, я предлагаю НЕ ИСПОЛЬЗОВАТЬ глобальную переменную, чтобы сохранить ссылку на SqlConnection. Это дорогостоящий ресурс, и если вы забудете закрыть и удалить его, это может существенно повлиять на производительность и стабильность вашего приложения.
В подобных ситуациях использование инструкции — это все, что вам действительно нужно.

using(SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings
                             ["ConnectionString"].ConnectionString));
{
    con.Open();
    SqlCommand cmd = new SqlCommand("insert into [Table] values(@fnam, @lnam, @pNum)", con);
    cmd.Parameters.AddWithValue("@fnam", txtfName.Text );
    cmd.Parameters.AddWithValue("@lnam", txtlName.Text );
    cmd.Parameters.AddWithValue("@pNum", txtpNumber.Text);
    cmd.ExecuteNonQuery();
}

Конечно убрать глобальную переменную и открыть в Page_Load

person Steve    schedule 19.05.2013
comment
+1, но я также считаю, что вам нужно сделать свой sql как: insert into [Table] values...., потому что таблица на самом деле является именем, которое используется: -/ и является зарезервированным ключевым словом. - person Aristos; 20.05.2013
comment
Да @Aristos, я также добавил это, ища правильную ссылку, чтобы добавить к ответу - person Steve; 20.05.2013
comment
Во-первых, это фактическая ошибка, но хорошо дать ему этот полный ответ. Имя Table очень простое, как и select :), когда вы создаете таблицу! Имейте это и на их вопрос:)... - person Aristos; 20.05.2013
comment
@Стив. иметь глобальную переменную для хранения ссылки на SqlConnection - правда? Для этого и нужен пул соединений. Сохранение собственного глобального соединения в большинстве случаев не считается лучшей практикой. См., например, stackoverflow.com/a/10116623/1945631. - person Andy Brown; 20.05.2013
comment
Я предлагаю НЕ иметь глобальную переменную для сохранения ссылки на SqlConnection, потому что пул соединений делает этот подход контрпродуктивным. Я неправильно понял ваш комментарий? - person Steve; 20.05.2013
comment
@Стив. Не ясно. Я перечитал вашу фразу и теперь понял. Могу я предложить вам отредактировать и перефразировать? Извините за слишком напористый комментарий. - person Andy Brown; 20.05.2013
comment
Буду реализовывать этот метод, спасибо за информацию. У меня также есть несколько дополнительных вопросов о базе данных. У меня есть довольно обширная форма, которую группа людей будет заполнять для отправки в базу данных и, в свою очередь, иметь тип интрасети, который извлекает эти данные. Что является хорошей практикой, когда форма отправляется в базу данных? Только один раз идеально или несколько раз будет просто отлично? Мне посоветовали обращаться к базе данных только один раз за сеанс. Кроме того, могу ли я использовать стандартные html-теги ‹input› для отправки в aspx или более/менее идеальные для использования веб-форм asp? Что ты думаешь? Любые другие указатели. - person Sean Robbins; 20.05.2013
comment
@SeanRobbins действительно начинает публиковать новые вопросы, вы получаете больше внимания. - person Steve; 20.05.2013
comment
@AndyBrown, обновлено, надеюсь, теперь стало понятнее (ну, это самый четкий текст, который я могу получить из GoogleTranslate) - person Steve; 20.05.2013
comment
Сделаю. Большое спасибо, ребята. Я собираюсь отметить это как завершенное. - person Sean Robbins; 20.05.2013

Ваш запрос пытается вставить в таблицу с именем Table. Это действительно существует? Если нет, то укажите фактическое имя таблицы в запросе. Если ваша таблица действительно называется Table, я настоятельно рекомендую изменить ее на что-то менее запутанное.

Кроме того, прекратите писать команды, объединяя текст сейчас. Узнайте, как использовать параметры для для предотвращения инъекций SQL

ИЗМЕНИТЬ

Оператор вставки использует формат, указанный в документах BOL для INSERT, и приведенные здесь примеры. Таблица — это ключевое слово, поэтому не используйте его в качестве имени таблицы. Если вам нужно использовать ключевое слово, вам нужно экранировать его, используя квадратные скобки. См. раздел BOL: идентификаторы с разделителями.

Я по-прежнему говорю, не используйте «Таблица» в качестве имени для таблицы. Сделайте свою жизнь проще.

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

person Andy Brown    schedule 19.05.2013
comment
+1 за указание конкретной проблемы. Таблица с именем table не существует. - person pratik garg; 20.05.2013
comment
таблица в базе данных IS называется dbo.Table - person Sean Robbins; 20.05.2013
comment
На самом деле я думаю, что синтаксис вставки неверен, но большая проблема заключается в том, чтобы назвать таблицу Table и написать небезопасный код. - person Andy Brown; 20.05.2013
comment
@SeanRobbins Имя Table - это одно ключевое слово sql, измените свой sql как: insert into [Table] values.... и избегайте использования зарезервированных ключевых слов ... - person Aristos; 20.05.2013
comment
Изменено «вставить в значения таблицы» на «вставить в значения [таблицы]», и все работает нормально. Энди, ты SH$T! Спасибо Обратите внимание на себя, держитесь подальше от простых имен. - person Sean Robbins; 20.05.2013
comment
@ШонРоббинс. Нет проблем, см. мое недавнее редактирование для получения дополнительной информации. И, пожалуйста, ознакомьтесь с документацией OWASP и узнайте, почему SQL-инъекция одновременно важно предотвратить и легко избежать использования параметров. Никогда больше не пишите небезопасный код, и в результате вы будете более востребованы. - person Andy Brown; 20.05.2013

Изменено «вставить в значения таблицы» на «вставить в значения [таблицы]», и все работает нормально. Спасибо Обратите внимание на себя, держитесь подальше от простых имен.

person Sean Robbins    schedule 21.05.2013

Везде, где вы используете ExecuteNonQuery(), вы должны поймать SqlException или вам нужно выбросить из своей функции.

В приведенном выше случае Button1_Click — это функция, использующая ExecuteNonQuery() из класса SqlCommand.

Теперь, что происходит, что эта функция ( ExecuteNonQuery ) имеет определение для выбрасывания SqlException. поэтому у вас есть два варианта: вы также можете генерировать SqlException или вы можете поместить эту строку в блок try catch для обработки исключения.

person pratik garg    schedule 19.05.2013