Новый триал. Сборка 13084.
Привет всем.
На сайте провайдера выложен новый триал, в котором исправлена одна мелкая, но досадная ошибка.
При тестировании провайдера через OLEDB.NET обнаружилось, что провайдер некорректно обрабатывает нулевые ссылки (null), передаваемые через значения параметров запросов.
using System; using System.Data; using NUnit; using NUnit.Framework; using sys_oledb=System.Data.OleDb; //////////////////////////////////////////////////////////////////////////////// //class Test_04__bug_with_null_value public static class Test_04__bug_with_null_value { [Test] public static void Test_01__Integer() { //Connection string from application settings string cn_str=TestServices.Conf__GetCnStr(); using(var cn=new sys_oledb.OleDbConnection(cn_str)) { cn.Open(); using(var tr=cn.BeginTransaction(IsolationLevel.RepeatableRead)) { var cmd=new sys_oledb.OleDbCommand("insert into TEST_MODIFY_ROW (COL_INTEGER) values(?) returning (COL_INTEGER)",cn,tr); cmd.Parameters.Add(null,sys_oledb.OleDbType.Integer).Value=null; cmd.Parameters[0].Direction=ParameterDirection.Input; cmd.Parameters.Add(null,sys_oledb.OleDbType.Integer).Value=111; cmd.Parameters[1].Direction=ParameterDirection.Output; var rows_affected=cmd.ExecuteNonQuery(); Assert.That(rows_affected,Is.EqualTo(1)); Assert.That(cmd.Parameters[1].Value,Is.SameAs(DBNull.Value)); }//using tr }//using cn }//Test_01__Integer //----------------------------------------------------------------------- [Test] public static void Test_02__TimeStamp() { //Connection string from application settings string cn_str=TestServices.Conf__GetCnStr(); using(var cn=new sys_oledb.OleDbConnection(cn_str)) { cn.Open(); using(var tr=cn.BeginTransaction(IsolationLevel.RepeatableRead)) { var cmd=new sys_oledb.OleDbCommand("insert into TEST_MODIFY_ROW (COL_TIMESTAMP) values(?) returning (COL_TIMESTAMP)",cn,tr); cmd.Parameters.Add(null,sys_oledb.OleDbType.DBTimeStamp).Value=null; cmd.Parameters[0].Direction=ParameterDirection.Input; cmd.Parameters.Add(null,sys_oledb.OleDbType.DBTimeStamp).Value=DateTime.Now; cmd.Parameters[1].Direction=ParameterDirection.Output; var rows_affected=cmd.ExecuteNonQuery(); Assert.That(rows_affected,Is.EqualTo(1)); Assert.That(cmd.Parameters[1].Value,Is.SameAs(DBNull.Value)); }//using tr }//using cn }//Test_02__TimeStamp };//class Test_04__bug_with_null_value ////////////////////////////////////////////////////////////////////////////////
В первом тесте получалось, что провайдер записывал в базу нулевое значение. И, соответственно, получал его через OUT-параметр.
А во втором — провайдер возвращает ошибку вида:
System.Data.OleDb.OleDbException : Ошибка формирования ib-значения входящего параметра. Позиция 0.
Ошибка формирования ISC_DATE. Некорректный элемент [month]. Допустимый диапазон [1..12].
Год: 0. Месяц: 0. День: 0.
—-> System.InvalidOperationException : Поставщик не смог определить значение DateTime. Например, строка только что была создана, значение по умолчанию для столбца DateTime не было доступно, а потребитель еще не задал нового значения DateTime.
Начиная с новой сборки (13084) провайдер будет трансформировать такие значения параметров в NULL и вышеуказанные тесты будут отрабатывать без проблем.
Немного более подробное описание проблемы.
Вообще говоря, null это не тоже самое что и DBNull.Value. OLEDB.NET передает null-ссылки как данные с состоянием DBSTATUS_S_DEFAULT. А DBNull.Value — как данные с состоянием DBSTATUS_S_ISNULL.
Формально, DBSTATUS_S_DEFAULT означает, что провайдер должен использовать значение по-умолчанию, которое задано для связанной колонки. Однако ни FB, ни IB на текущий момент не поддерживают указание использования DEFAULT значения колонки для параметра запроса. Поэтому приходится передавать NULL. Если я ничего не упустил в этом вопросе.
В дальнейшем, когда такая функциональность будет добавлена в сервер, поведение DBSTATUS_S_DEFAULT будет изменено на правильное. Так что, чисто практический совет, который избавит от неприятных неожиданностей в будущем — используйте DBNull.Value вместо null.
Другое.
В новом триале все бинарники (и 32 и 64 бита) собраны с помощью VS2010.
Ксения on 25 декабря, 2011
Ммм, заюзали 2010 студию. Поздравляю! IntelliSense там куда приятнее.
P.S. Неужели Вы так любите плюсы? Или у Вас богатое прошлое как кодера на Си? 🙂