Parametrizar consulta SQL

Muchas publicaciones sobre Parámetros en SQL con C # pero aún me falta algo. No recibo un post de error pero no se insertan datos. ¿Lo que falta? Tengo cuadros de text llamados fname, lname, address, city, state y 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(); } 

Así que cambié a esto y todavía no pasa nada.

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

Olvidaste ejecutar el command;)

EDITAR: tampoco usaste los parameters que creaste al principio del método.

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

Por cierto, no hagas cosas como esas:

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

Es inútil, solo agrega un nuevo nivel de exception sin agregar nada útil. Solo deja que la exception suba la stack hasta que llegue a un bloque catch que realmente hace algo útil.

Los problemas key en la muestra proporcionada son:

  • La definición de sqlstring debe tener las definiciones de parameters en la cadena
  • La stack de llamadas se restablece cuando se produce el error creando un nuevo object de error
  • El object SqlConnection y SqlCommand no se eliminan correctamente (por ejemplo, la llamada conn.Close() no forma parte de la sección Finally del manejador de excepciones.
  • El Value de los SqlParameters no se establece
  • El método Execute xx en el object SqlCommand no comienza a llamarse
  • Los valores de cadena se almacenan en un tipo varchar , no en Text . El text es el tipo de datos de SQL Server en desuso para almacenar blob.

Refactorizaría el código de la siguiente manera:

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

Nota: prefiero suministrar el tipo de datos de los parameters, ya que SqlCE no siempre funciona correctamente cuando no se suministra ningún tipo.

Hay muchas maneras de hacerlo. Una de las forms es replace las líneas en el bloque try con:

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

Si haces eso, no necesitas todas las inicializaciones de SqlParameter

Y obviamente necesitas ejecutar el command:

 comm.ExecuteNonQuery(); 

Esto será mucho más corto:

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

Pero antes que nada esto es lo que te perdiste:

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

y

 command.ExecuteNonQuery(); 

En primer lugar, no está ejecutando el command, deberá llamar a comm.ExecuteNonQuery(); , en segundo lugar, su cadena SQL será incorrecta. Esta línea:

 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) 

Puede ser:

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

En realidad, no está agregando sus parameters a su command. Usted crea un parámetro como ese:

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

Pero estás agregando esto:

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

sin reference a zipparam . Esto significa que el valor zippy nunca se agrega realmente al command. Podrías hacer esto todo en una línea usando:

 comm.Parameters.Add(new SqlParameter(@Zippy, SqlDbType.SmallInt)).Value = zippy; 

No sé cuál es el problema en su código, pero la mejor manera de averiguarlo es ejecutar su procedimiento almacenado dentro del server SQL con los parameters proporcionados.

Si el procedimiento almacenado no se ejecuta correctamente, entonces el error estará en su procedimiento almacenado y no en el código.