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