2012-08-23 9 views
15

Voglio implementare un semplice pulsante di cancellazione per il mio database. Il metodo di evento simile a questa:Come riutilizzare il parametro SqlCommand attraverso ogni iterazione?

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

ma ottengo questo messaggio:

Un @id variabile è stata dichiarata. I nomi delle variabili devono essere univoci all'interno di un batch di query o stored procedure.

Esiste un modo per riutilizzare questa variabile?

risposta

42

Parameters.AddWithValue aggiunge un nuovo parametro per il comando. Dato che lo stai facendo in un loop con lo stesso nome, stai ricevendo l'eccezione "I nomi delle variabili devono essere univoci".

Quindi è necessario un solo parametro, aggiungerlo prima del ciclo e modificare solo il suo valore nel ciclo.

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

Un altro modo è quello di utilizzare command.Parameters.Clear(); prima. Quindi è anche possibile aggiungere i parametri nel ciclo senza creare lo stesso parametro due volte.

0

L'errore è perché si aggiunge lo stesso parametro più volte in ogni iterazione del ciclo.

Sposterei quel codice in un metodo separato in modo da poterlo chiamare da più punti in base alle esigenze.

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

} 

Poi chiamare in questo modo

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

Piuttosto che:

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

Usa qualcosa come:

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

Al di fuori del foreach, e solo impostare manualmente all'interno del ciclo:

p.ParameterName = "@ID"; 
p.Value = rowUserID; 
Problemi correlati