【问题标题】:Parameterize SQL query参数化 SQL 查询
【发布时间】:2012-06-09 13:19:27
【问题描述】:

许多关于 C# 中的 SQL 参数的帖子,但我仍然缺少一些东西。我没有收到错误消息,但没有插入数据。缺什么?我有名为 fname、lname、address、city、state 和 zip 的文本框。

 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

标签: c# .net sql tsql ado.net


【解决方案1】:

你忘记执行命令了;)

编辑:您也没有使用在方法开始时创建的参数。

    ...
    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 在他的回答中指出了这一点。
【解决方案2】:

提供的示例中的关键问题是:

  • sqlstring的定义应该有字符串中的参数定义
  • 通过创建新的错误对象引发错误时,调用堆栈正在重置
  • SqlConnectionSqlCommand 对象未正确开始处理(例如,conn.Close() 调用不是异常处理程序的 Finally 部分的一部分。
  • SqlParametersValue 未设置
  • SqlCommand 对象上的Execute xx 方法未开始调用
  • 字符串值存储在varchar 类型中,而不是Text。 Text 是已弃用的用于存储 blob 的 SQL Server 数据类型。

我将重构代码如下:

     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();
        }
    }

注意:我更喜欢提供参数的数据类型,因为当没有提供类型时,SqlCE 并不总是能正常工作。

【讨论】:

  • 它说它不能接受字符串。 var first、last 等被设置为字符串,但 sql 字符串使用 @first 等设置,而不是参数之前的值。addRange();我需要首先为 SqlParameters 设置值,所以当设置 SQL 字符串时,它是使用 SqlParameter.Values 设置的,对吗?我不能只移动 AddRange,因为这样 SqlCommand 没有初始化,这在初始化之前的每个命令调用都会引发错误。
  • 我在 sql 字符串中添加了缺少的括号
  • 另外,数据类型应该是Varchar,而不是text
  • 在数组中我最终创建了一个 sqlParameter 数组并像这样分配每个索引: sqlparam[0] = new SqlParameter(@"first", SqlDbType.Text); sqlparam[0].Value = first;这可以分配数组中的值,然后调用: comm.Parameters.AddRange(sqlparam);
【解决方案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();

【讨论】:

  • 所以我改成这个了,还是没有任何反应。
  • @marcmiller2007:再次验证您是否为参数设置了值,并将其添加到命令中。然后你执行命令。还要检查连接字符串。
【解决方案4】:

有很多方法可以解决这个问题。其中一种方法是将 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();

【讨论】:

    【解决方案5】:

    首先你没有执行命令,你需要调用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;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多