Параметризованные запросы C # для Oracle - серьезная и опасная ошибка! - PullRequest
36 голосов
/ 07 октября 2010

Это абсолютный ревун.Я не могу поверить своим собственным глазам, и я не могу поверить, что никто до меня не обнаружил бы это, если бы это была настоящая ошибка в 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 ]

44 голосов
/ 07 октября 2010

Это не ошибка, но она явно упоминается в документации Oracle ODP.Net. В классе OracleCommand параметры связаны положением по умолчанию. Если вы хотите выполнить привязку по имени, установите свойство cmd.BindByName = true; явно.

Ссылка на документацию Oracle. http://download.oracle.com/docs/cd/E11882_01/win.112/e12249/OracleCommandClass.htm#i997666

4 голосов
/ 07 октября 2010

Это опечатка, которую вы добавили column3 перед column2?

Поскольку синтаксис двоеточия означает переменную связывания - имя не имеет значения для переменных BIND в 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 BIND.

0 голосов
/ 06 июня 2013
p.Add(":Column1", 1);
p.Add(":Column2", "record 1");
p.Add(":Column3", null);

// ПРИМЕЧАНИЕ. Я добавил: к именам параметров, которые будут распознаваться клиентом данных Oracle

...