参数化SQL查询

很多关于SQL中带有C#的参数的post,但我仍然遗漏了一些东西。 我没有收到错误消息但没有插入数据。 缺什么? 我有名为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(); 

你忘了执行命令;)

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

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

它没用,它只是添加了一个新的exception级别而没有添加任何有用的东西。 只是让exception在堆栈中冒泡,直到它到达一个实际上有用的catch块。

提供的样本中的关键问题是:

  • sqlstring的定义应该在字符串中包含参数定义
  • 通过创建新的错误对象引发错误时,将重置调用堆栈
  • SqlConnectionSqlCommand对象未正确开始处理(例如, conn.Close()调用不是exception处理程序的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并不总是正常工作。

这将更短:

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

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

首先你没有执行命令,你需要调用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; 

我不知道你的代码有什么问题,但找到它的最好方法是使用提供的参数在SQL服务器内部执行你的存储过程。

如果存储过程未成功执行,则错误将在您的存储过程中而不是在代码中。