Вопрос по c#, .net, sql, ado.net – Параметризация SQL-запроса

4

Много сообщений о параметрах в SQL с C #, но я все еще что-то упускаю. Я не получаю сообщение об ошибке, но данные не вставлены. Чего не хватает? У меня есть текстовые поля с именем fname, lname, адрес, город, штат и почтовый индекс.

 private void enter_button_Click(object sender, EventArgs e)
 {
    string first, last, addy, city1, stat, zippy;
    first = fname.Text; 
    SqlParameter firstparam;
    firstparam = new SqlParameter();
    firstparam.ParameterName = "@first";
    firstparam.Value = first;
    last = lname.Text;
    SqlParameter lastparam;
    lastparam = new SqlParameter();
    lastparam.ParameterName = "@last";
    lastparam.Value = last;
    addy = address.Text;
    SqlParameter addressparam;
    addressparam = new SqlParameter();
    addressparam.ParameterName = "@addy";
    addressparam.Value = addy;
    city1 = city.Text;
    SqlParameter cityparam;
    cityparam = new SqlParameter();
    cityparam.ParameterName = "@city1";
    cityparam.Value = city1;
    stat = state.Text;
    SqlParameter stateparam;
    stateparam = new SqlParameter();
    stateparam.ParameterName = "@stat";
    stateparam.Value = stat;
    zippy = zip.Text;
    SqlParameter zipparam;
    zipparam = new SqlParameter();
    zipparam.ParameterName = "@zippy";
    zipparam.Value = zippy;

    try
    {
        Validate(fname);
        Validate(lname);
        Validate(city);
        Validate(state);
    }
    catch (Exception ex)
    {
        throw new Exception(ex.ToString(), ex);
    }

    try
    {
        exValidate(address);
    }
    catch (Exception ex1)
    {
        throw new Exception(ex1.ToString(), ex1);
    }

    try
    {
        numValidate(zip);
    }
    catch (Exception ex2)
    {
        throw new Exception(ex2.ToString(), ex2);
    }


    string connection = "Data Source=TX-MANAGER;Initial Catalog=Contacts;Integrated Security=True";
    var sqlstring = string.Format("INSERT INTO Contacts ([First] ,[Last] ,[Address] ,[City] ,[State],[ZIP]) VALUES {0}, {1}, {2}, {3}, {4}, {5})", @first, @last, @addy, @city1, @stat, @zippy);
    SqlConnection conn = new SqlConnection(connection);
    SqlCommand comm = new SqlCommand();
    comm.CommandText = sqlstring;
    try
    {
        conn.Open();
        //SqlTransaction trans = conn.BeginTransaction();
        //comm.Transaction = trans;
        comm.Parameters.Add("@first", SqlDbType.Text);
        comm.Parameters.Add("@last", SqlDbType.Text);
        comm.Parameters.Add("@addy", SqlDbType.Text);
        comm.Parameters.Add("@city1", SqlDbType.Text);
        comm.Parameters.Add("@stat", SqlDbType.Text);
        comm.Parameters.Add("@zippy", SqlDbType.SmallInt);
    }
    catch (Exception commex)
    {
        throw new Exception(commex.ToString(), commex);
    }
    conn.Close();
}

Так что я изменился на это и до сих пор ничего не происходит

     string connection = "Data Source=TX-MANAGER;Initial Catalog=Contacts;Integrated Security=True";
        var sqlstring = string.Format("INSERT INTO Contacts ([First] ,[Last] ,[Address] ,[City] ,[State],[ZIP]) VALUES {0}, {1}, {2}, {3}, {4}, {5})", @first, @last, @addy, @city1, @stat, @zippy);
        SqlConnection conn = new SqlConnection(connection);
        SqlCommand comm = conn.CreateCommand();
        comm.CommandText = sqlstring;
        try
        {
            conn.Open();
            //SqlTransaction trans = conn.BeginTransaction();
            //comm.Transaction = trans;
            comm.Parameters.AddWithValue("@first", first);
            comm.Parameters.AddWithValue("@last", last);
            comm.Parameters.AddWithValue("@addy", addy);
            comm.Parameters.AddWithValue("@city1", city1);
            comm.Parameters.AddWithValue("@stat", stat);
            comm.Parameters.AddWithValue("@zippy", zippy);
            comm.ExecuteNonQuery();
Ваше соединение не будет закрыто в случае исключения, поскольку вы повторно выбрасываете исключение в пункте catch иconn.Close() находится вне (не существует) блока finally. использованиеusing-statement вместо. Rango

Ваш Ответ

5   ответов
4

Ключевые вопросы в предоставленном образце:

  • The definition of the sqlstring should have the parameter definitions in the string
  • The Call Stack is being reset when the error is thrown by creating a new error object
  • The SqlConnection and SqlCommand object are not begin disposed correctly (for example, the conn.Close() call is not part of the Finally section of the exception handler.
  • The Value of the SqlParameters are not being set
  • The Execute xx method on the SqlCommand object is not begin called
  • String Values are stored in a varchar type, not Text. Text is the deprecated SQL Server datatype to store blob.

Я бы переформулировал код следующим образом:

     private void enter_button_Click(object sender, EventArgs e)
     {
        var first = fname.Text; 
        var last = lname.Text;
        var addy = address.Text;
        var city1 = city.Text;
        var stat = state.Text;
        var zippy = zip.Text;

        Validate(fname);
        Validate(lname);
        Validate(city);
        Validate(state);
        exValidate(address);
        numValidate(zip);

        using (var conn = new SqlConnection("Data Source=TX-MANAGER;Initial Catalog=Contacts;Integrated Security=True"))
        using (var cmd = new SqlCommand(@"INSERT INTO Contacts ([First], [Last], [Address], [City], [State], [ZIP]) VALUES (@first, @last, @addy, @city1, @stat, @zippy)", conn))
        {
            cmd.Parameters.AddRange(
                new[]
                    {
                        new SqlParameter(@"first", SqlDbType.VarChar).Value = first,
                        new SqlParameter(@"last", SqlDbType.VarChar).Value = last,
                        new SqlParameter(@"addy", SqlDbType.VarChar).Value = addy,
                        new SqlParameter(@"city1", SqlDbType.VarChar).Value = city1,
                        new SqlParameter(@"state", SqlDbType.VarChar).Value = stat,
                        new SqlParameter(@"zippy", SqlDbType.SmallInt).Value = zippy
                    });
            conn.Open();
            cmd.ExecuteNonQuery();
        }
    }

Note: I prefer supplying the datatype of parameters since SqlCE does not always work correctly when no type is supplied.

Кроме того, типы данных должны бытьVarcharнеtext
в массиве я создал массив sqlParameter и назначил каждый индекс следующим образом: sqlparam [0] = new SqlParameter (@ & quot; first & quot ;, SqlDbType.Text); sqlparam [0] .Value = первый; Это сработало для присвоения значений в массиве и затем вызвало: comm.Parameters.AddRange (sqlparam); marcmiller2007
он говорит, что не может принимать строки. переменная first, last и т. д. устанавливается в виде строки, но строка sql устанавливается с помощью @first и т. д. вместо значений перед параметрами .addRange (); Мне нужно сначала установить значения для SqlParameters, чтобы при установке строки SQL она задавалась с помощью SqlParameter.Values, верно? Я не могу просто переместить AddRange, потому что тогда SqlCommand не инициализируется, что выдает ошибки при каждом вызове команды перед его инициализацией. marcmiller2007
Я добавил пропущенные скобки в строке SQL
3

Это будет намного короче:

using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = connection.CreateCommand())
{
    command.CommandText = "INSERT INTO Contacts ([First], [Last], [Address], [City], [State], [ZIP]) VALUES (@first, @last, @address, @city, @state, @zip)";

    command.Parameters.AddWithValue("@first", first);
    // or
    // command.Parameters.Add("@first", SqlDbType.Type).Value = first;
    // ...

    connection.Open();
    command.ExecuteNonQuery();
}

Но прежде всего вот что вы пропустили:

comm.Parameters.Add(firstparam);
// instead of
// comm.Parameters.Add("@first", SqlDbType.Text);

а также

command.ExecuteNonQuery();
2

Есть много способов сделать это. Один из способов - заменить строки в блоке try на:

comm.Parameters.AddWithValue("@first", first);
comm.Parameters.AddWithValue("@last", last);
comm.Parameters.AddWithValue("@addy", addy);
comm.Parameters.AddWithValue("@city1", city1);
comm.Parameters.AddWithValue("@stat", stat);
comm.Parameters.AddWithValue("@zippy", zippy);

Если вы делаете это, вам не нужно всеSqlParameter инициализация

И вам, очевидно, нужно выполнить команду:

comm.ExecuteNonQuery();
2

Во-первых, вы не выполняете команду, вам нужно позвонитьcomm.ExecuteNonQuery();во-вторых, ваша строка SQL будет неправильной. Эта строка:

var sqlstring = string.Format("INSERT INTO Contacts ([First] ,[Last] ,[Address] ,[City],
[State],[ZIP]) VALUES {0}, {1}, {2}, {3}, {4}, {5})", @first, @last, @addy, @city1, 
@stat, @zippy)

Может быть просто:

var sqlstring = "INSERT INTO Contacts ([First] ,[Last] ,[Address] ,[City] ,[State],[ZIP]) 
                 VALUES (@first, @last, @addy, @city1, @stat, @zippy)";

В-третьих, вы фактически не добавляете свои параметры в вашу команду. Вы создаете параметр следующим образом:

SqlParameter zipparam;
zipparam = new SqlParameter();
zipparam.ParameterName = "@zippy";
zipparam.Value = zippy;

Но вы добавляете это:

comm.Parameters.Add("@zippy", SqlDbType.SmallInt);

без ссылки наzipparam, Это означает, что значениеzippy фактически никогда не добавляется в команду. Вы можете сделать все это в одну строку, используя:

comm.Parameters.Add(new SqlParameter(@Zippy, SqlDbType.SmallInt)).Value = zippy;
Вы можете написать толькоcomm.Parameters.Add("@Zippy", SqlDbType.SmallInt).Value = zippy;
6

Вы забыли выполнить команду;)

РЕДАКТИРОВАТЬ: вы также не использовали параметры, которые вы создали в начале метода.

    ...
    try
    {
        conn.Open();
        //SqlTransaction trans = conn.BeginTransaction();
        //comm.Transaction = trans;
        comm.Parameters.Add(firstparam);
        comm.Parameters.Add(lastparam);
        comm.Parameters.Add(addressparam);
        comm.Parameters.Add(cityparam);
        comm.Parameters.Add(stateparam);
        comm.Parameters.Add(zipparam);

        // This is what you forgot:
        comm.ExecuteNonQuery();
    }
    ...

Кстати, не делайте таких вещей:

    catch (Exception ex1)
    {
        throw new Exception(ex1.ToString(), ex1);
    }

Это бесполезно, оно просто добавляет новый уровень исключений, не добавляя ничего полезного. Просто позвольте исключению пузыриться в стеке, пока оно не достигнет блока catch, который на самом деле делает что-то полезное.

Кроме того, все его параметры SqlParameters (firstparam, lastparam и т. Д.) Не связаны с SqlCommand (comm) SqlParameterCollection
Я думаю, что вы не правы: посмотрите, добавленные параметры не имеют значения. Параметры со значениями не были добавлены.
Хорошо. В коде было много недостатков. Сам по себе встроенный оператор SQL неверен. @GarethD указал на это в своем ответе.
@JohnGathogo, ты прав. Я исправил свой ответ.

Похожие вопросы