Как повторно использовать параметр SqlCommand через каждую итерацию?
Я хочу реализовать простую кнопку удаления для моей базы данных. Метод события выглядит примерно так:
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;
}
}
но я получаю это сообщение:
Объявлена переменная @id. Имена переменных должны быть уникальными в пределах пакет запросов или хранимая процедура.
Можно ли повторно использовать эту переменную?
Ответы
Ответ 1
Parameters.AddWithValue
добавляет новый параметр в команду. Поскольку вы делаете это в цикле с тем же именем, вы получаете исключение "Имена переменных должны быть уникальными".
Итак, вам нужен только один параметр, добавьте его перед циклом и измените только его значение в цикле.
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;
// ...
}
Другой способ - сначала использовать command.Parameters.Clear();
. Затем вы можете также добавить параметр в цикле, не создавая тот же параметр дважды.
Ответ 2
Вместо
command.Parameters.AddWithValue("@id", rowUserID);
Используйте что-то вроде:
System.Data.SqlClient.SqlParameter p = new System.Data.SqlClient.SqlParameter();
За пределами foreach и просто установите вручную внутри цикла:
p.ParameterName = "@ID";
p.Value = rowUserID;
Ответ 3
Ошибка в том, что вы добавляете один и тот же параметр снова и снова в каждой итерации цикла.
Я бы переместил этот код в отдельный метод, чтобы я мог его вызвать из нескольких мест по мере необходимости.
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;
}
}
Затем назовите его следующим образом
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
}
}