Тэги

Silverlight (36) WPF (10) IIS (7) Visual Studio (7) SharePoint (6) .Net Framework (5) ODP.NET (5) ASP.NET (4) C# (4) common (4) Network Settings (3) JavaScript (2) MS Office (2) Resharper (2) WCF (2) WEB (2) XPath (2) XSLT (2) ADO.NET (1) APEX (1) CMD (1) CSS (1) EF (1) HTML (1) Hardware bugs (1) Java (1) MS SQL (1) Oracle (1) PDF (1) Version Control (1) XAML (1)

четверг, 9 сентября 2010 г.

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.

Комментариев нет:

Отправить комментарий