У вас есть несколько проблем с приведенным выше примером кода, которые должны помешать его работе.Я немного шокирован тем, что закомментированная строка кода работает.
- Вы не цитируете значения, которые вы обновляете
- Даже если вы их цитировали, вам следует вместо этого использовать параметры.
- Устройство чтения данных предназначено для чтения.Если вы выполняете DML, вы должны использовать
ExecuteNonQuery
.Если у вас есть возвращаемые значения, может быть причина для чтения данных, но в этом случае вам это не нужно.
Все это говорит о том, что динамический SQL иногда неизбежен, но я быРекомендовать все возможные способы, прежде чем сдаться и сделать динамический SQL.Если вам необходимо, одним из способов смягчения этого может быть конечное количество параметров, поэтому вместо того, чтобы позволить им обновлять ЛЮБОЕ поле, пусть они выбирают поле из списка параметров.
Это все еще динамичноSQL, но он по крайней мере параметризован, и возможности внедрения по крайней мере ограничены методом, который делает маловероятным любое внедрение.
public enum ActorField
{
FirstName,
LastName,
Salutation
}
public void UpdateActorField(string OldName, string NewName, ActorField FieldId)
{
string sql = "update actor set {0} = :NEW_NAME where {0} = :OLD_NAME";
switch (FieldId)
{
case ActorField.FirstName
sql = string.Format(sql, "first_name");
break;
case ActorField.LastName
sql = string.Format(sql, "last_name");
break;
case ActorField.Salutation
sql = string.Format(sql, "salutation");
break;
}
using (NpgsqlCommand cmd = new NpgsqlCommand(sql, connection))
{
cmd.Parameters.AddWithValue("NEW_NAME", NewName);
cmd.Parameters.AddWithValue("OLD_NAME", OldName);
int updatedRows = cmd.ExecuteNonQuery();
}
}
Существуют более ловкие способы сделать это с помощью одного оператора SQL и с помощьюнет динамического SQL, но они добавляют большую сложность к тому, что должно быть простой проблемой.