ODP.NET: Тонкости биндинга переменных.



“Сколько же можно наступать на грабли от Oracle”, сказал я себе и решил написать этот пост.

ODP.NET это реализация ADO.NET для работы с Oracle.

Перечислю некоторые тонкости биндинга параметров в ODP.NET.

Изначально имеем код запроса, который корректнен и работает:
Начальный пример
var oCom = new OracleCommand
{
    CommandText = @"begin :outP := krn_setting_iapi.get_v(:inpP1,:inpP2,:inpP3); end;",
};
oCom.Parameters.Add("outP", OracleDbType.Varchar2, 100, null, ParameterDirection.Output);
oCom.Parameters.Add("inpP1", OracleDbType.Varchar2, 20, "first", ParameterDirection.Input);
oCom.Parameters.Add("inpP2", OracleDbType.Varchar2, 20, "second", ParameterDirection.Input);
oCom.Parameters.Add("inpP3", OracleDbType.Varchar2, 20, "first", ParameterDirection.Input);

Тонкость 1. Называется “У вас нет такого геммора? Тогда Oracle идет к вам! ”.
Просто так менять порядок биндинга переменных в коде нельзя.
oCom.Parameters.Add("inpP1", OracleDbType.Varchar2, 20, "version", ParameterDirection.Input);
oCom.Parameters.Add("outP", OracleDbType.Varchar2, 100, null, ParameterDirection.Output);
Если вы хотите так сделать, то вам нужно добавить следующую строкчку:
oCom.BindByName = true;
Иначе ODP.NET выдаст тут вам разные исключения, возможно ORA-01403: no data found или/и ORA-06512, ну или ORA-20000.

Тонкость 2. Называется “Геммор - наш стиль!”.
В начальном примере, в параметре inpP1 и inpP3, передается одинаковое значение, но вы не можете сократить количество переменных и следующая запись будет некорректна:
var oCom = new OracleCommand
{
    CommandText = @"begin :outP := krn_setting_iapi.get_v(:inpP1,:inpP2,:inpP1); end;",
};
Не попадитесь на этом!!!
Возможно, положение может исправить строчка кода “oCom.BindByName = true;”, но я сейчас этого не помню точно.

Токость 3. “Мы хуже чем ты думаешь.”
Это практически бага и касается она использования типа параметра OracleDbType.Varchar2 (т.е. оракловый String).
Это может быть не во всех версиях ODP.NET, но встречается часто.
Для этого типа обязательно задайте размер (size), у нас выше в примере это цифры 100 и 20. Детально об этом здесь.
К этому относится и следующее:
метод Parameters.Add(…) в классе OracleCommand не имеет перегрузки для передачи размерности без передачи значения параметра, если еще надо передать ParameterDirection.
По человечески это значит, что вы думаете, что в следующей строке вы зададите размерность для Varchar2 в 100:
oCom.Parameters.Add("outP", OracleDbType.Varchar2, 100, ParameterDirection.Output);
Но на самом деле вы задаете так значение параметра в 100.ToString(), поэтому строка выше работать не будет.
ODP.NET выдаст ошибку: ORA-06502: PL/SQL: numeric or value error: character string buffer too small.

Комментарии

Популярные сообщения из этого блога

A4tech. Мышь не найдена. Пожалуйста, подсоедините мышь.

SVN: Пропали иконки TortoiseSVN.

Ускорение компиляции Visual Studio Solution методом "Copy Local = False".