2012-08-23 18 views
15

Quiero implementar un botón de eliminación simple para mi base de datos. El método de evento es como la siguiente:¿Cómo reutilizar el parámetro SqlCommand en cada iteración?

private void btnDeleteUser_Click(object sender, EventArgs e) 
{ 
    if (MessageBox.Show("Are you sure?", "delete users",MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK) 
    { 
     command = new SqlCommand(); 
     try 
     { 
      User.connection.Open(); 
      command.Connection = User.connection; 
      command.CommandText = "DELETE FROM tbl_Users WHERE userID = @id"; 
      int flag; 
      foreach (DataGridViewRow row in dgvUsers.SelectedRows) 
      { 
       int selectedIndex = row.Index; 
       int rowUserID = int.Parse(dgvUsers[0,selectedIndex].Value.ToString()); 

       command.Parameters.AddWithValue("@id", rowUserID); 
       flag = command.ExecuteNonQuery(); 
       if (flag == 1) { MessageBox.Show("Success!"); } 

       dgvUsers.Rows.Remove(row); 
      } 
     } 
     catch (SqlException ex) 
     { 
      MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information); 
     } 
     finally 
     { 
      if (ConnectionState.Open.Equals(User.connection.State)) 
       User.connection.Close(); 
     } 
    } 
    else 
    { 
     return; 
    } 
} 

pero me da este mensaje:

Un @id variable ha sido declarada. Los nombres de las variables deben ser únicos dentro de un lote de consulta o un procedimiento almacenado.

¿Hay alguna forma de reutilizar esta variable?

Respuesta

42

Parameters.AddWithValue añade un nuevo parámetro al comando. Como está haciendo eso en un bucle con el mismo nombre, obtiene la excepción "Los nombres de las variables deben ser únicos".

Así que solo necesita un parámetro, agréguelo antes del bucle y solo cambie su valor en el bucle.

command.CommandText = "DELETE FROM tbl_Users WHERE userID = @id"; 
command.Parameters.Add("@id", SqlDbType.Int); 
int flag; 
foreach (DataGridViewRow row in dgvUsers.SelectedRows) 
{ 
    int selectedIndex = row.Index; 
    int rowUserID = int.Parse(dgvUsers[0,selectedIndex].Value.ToString()); 
    command.Parameters["@id"].Value = rowUserID; 
    // ... 
} 

Otra forma es utilizar command.Parameters.Clear(); primero. Luego también puede agregar los parámetros en el ciclo sin crear el mismo parámetro dos veces.

0

El error se debe a que está agregando el mismo parámetro una y otra vez en cada iteración del ciclo.

Me gustaría mover ese código a un método separado para que pueda llamar desde varios lugares según sea necesario.

public bool DeleteUser(int userId) 
{ 
    string connString = "your connectionstring"; 
    try 
    { 
     using (var conn = new SqlConnection(connString)) 
     { 
     using (var cmd = new SqlCommand()) 
     { 
      cmd.Connection = conn; 
      cmd.CommandType = CommandType.Text; 
      cmd.CommandText = "DELETE FROM tbl_Users WHERE userID = @id"; 
      cmd.Parameters.AddWithValue("@id", userId); 
      conn.Open(); 
      cmd.ExecuteNonQuery(); 
      return true; 
     } 
     } 
    } 
    catch(Exception ex) 
    { 
     //Log the Error here for Debugging 
     return false; 
    } 

} 

Entonces llamarlo como esto

foreach (DataGridViewRow row in dgvUsers.SelectedRows) 
{ 
    int selectedIndex = row.Index; 
    if(dgvUsers[0,selectedIndex]!=null) 
    { 
    int rowUserID = int.Parse(dgvUsers[0,selectedIndex].Value.ToString()); 
    var result=DeleteUser(rowUserID) 
    } 
    else 
    { 
     //Not able to get the ID. Show error message to user 
    } 
} 
3

En lugar de:

command.Parameters.AddWithValue("@id", rowUserID); 

usar algo como:

System.Data.SqlClient.SqlParameter p = new System.Data.SqlClient.SqlParameter(); 

Fuera del foreach, y acaba de establecer manualmente el interior del bucle:

p.ParameterName = "@ID"; 
p.Value = rowUserID; 
Cuestiones relacionadas