C# параметризованные запросы для Oracle-серьезная и опасная ошибка!
это абсолютный ревун. Я не могу поверить своим глазам, и я не могу поверить, что никто до меня не обнаружил бы это, если бы это была настоящая ошибка в C#, поэтому я выпускаю ее для остальной части сообщества разработчиков, чтобы сказать мне, что я делаю неправильно. Я уверен, что этот вопрос будет включать меня, говоря: "DOH!- и очень сильно стукнул меня по голове ладонью - но все равно...
для тестирования я создал таблицу Test_1
, С сценарий следующим образом:
CREATE TABLE TEST_1 (
COLUMN1 NUMBER(12) NOT NULL,
COLUMN2 VARCHAR2(20),
COLUMN3 NUMBER(12))
TABLESPACE USERS
STORAGE (
INITIAL 64K
MAXEXTENTS UNLIMITED
)
LOGGING;
теперь я выполняю следующий код:
var conn = new OracleConnection("connectionblahblah");
conn.Open();
var cmd = conn.CreateCommand();
cmd.CommandText =
"insert into Test_1(Column1, Column2, Column3) " +
"values(:Column1, :Column2, :Column3)";
var p = cmd.Parameters;
p.Add("Column1", 1);
p.Add("Column3", null);
p.Add("Column2", "record 1");
cmd.ExecuteNonQuery();
Эй! Я получаю ошибку ORA-01722 - "неверный номер"! Но что случилось? Column1
является числовым и имеет значение 1, так что это нормально;Column2
- это строка, а Column3
является нулевым столбцом, так что это не должно вызвать никаких проблем...
теперь сядьте для этого... проблема здесь в том, что Column3
и Column2
транспонируются в том порядке, в котором они были добавлены к OracleParameterCollection
. Переключите их, и готово! Работает!
p.Add("Foo", 1);
p.Add("Bar", "record 1");
p.Add("hahahahahahaha", null);
думаешь, это сработает? Ну угадайте, что-это тут!
я сижу здесь, совсем обалдели. Я не могу поверить в то, что я вижу, и я также не могу поверить, что никто до меня не обнаружил это поведение (если я не знаю, как использовать Google правильно.)
это не просто неприятно - это опасно. Что бы произошло, если бы я транспонировал два столбца одного и того же типа данных? Я бы даже не получил ошибку - я бы просто вставил неправильные данные в неправильные столбцы и не был бы мудрее.
есть ли у кого - нибудь идеи для обходного пути-кроме как просто быть осторожным, чтобы не добавлять параметры в неправильном порядке?
3 ответов
Это не ошибка, но явно упоминается в Oracle ODP.Net документация. В классе OracleCommand параметры по умолчанию привязаны к позиции. Если вы хотите привязать по имени, установите свойство cmd.BindByName = true;
явно.
ссылка на документацию Oracle. http://download.oracle.com/docs/cd/E11882_01/win.112/e12249/OracleCommandClass.htm#i997666
это опечатка, которую вы добавили column3 перед column2?
поскольку синтаксис двоеточия означает переменную bind -- name не имеет значения для привязки переменных в PLSQL, они заполняются в порядке отправки. Это означает, что вы попытаетесь установить значение column2 как "запись 1", что объяснит ошибку недопустимого числа...
в настоящее время у вас есть:
p.Add("Column1", 1);
p.Add("Column3", null);
p.Add("Column2", "record 1");
...посмотрите, исправляет ли это изменение выпуск:
p.Add("Column1", 1);
p.Add("Column2", "record 1");
p.Add("Column3", null);
получение именованных параметров для работы?
Я должен отложить кому-то с большим опытом C#, чтобы объяснить, как заставить именованные параметры работать. Но я рад, что мы подтвердили, что двоеточие, похоже, интерпретируется как переменная привязки Oracle.
p.Add(":Column1", 1);
p.Add(":Column2", "record 1");
p.Add(":Column3", null);
/ / примечание Я добавил: к именам параметров, которые будут распознаны oracle data client