Новый триал. Сборка 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. Неужели Вы так любите плюсы? Или у Вас богатое прошлое как кодера на Си? 🙂