Logo    
Деловая газета CitCity.ru CITKIT.ru - все об Open Source Форумы Все публикации Учебный центр Курилка
CitForum    CITForum на CD    Подписка на новости портала Море(!) аналитической информации! :: CITFORUM.RU
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

24.02.2017

Google
WWW CITForum.ru
С Новым годом!
2006 г.

Руководство по работе с БД Firebird с использованием библиотеки ADO .Net 2.0

Меркулов Андрей Александрович, http://www.ibprovider.com/

Предисловие

В данном обзоре будет описан один из способов работы с базой данных Firebird в среде .Net при помощи управляемого Ole Db провайдера. Несомненным преимуществом сервера баз данных Firebird является его бесплатность в сравнении с существующими, не очень дешевыми аналогами (прежде всего MS SQL Server и ORACLE).

Firebird можно использовать для систем практически любого уровня, начиная от однопользовательских настольных приложений со встроенной базой данных (Embed Database), до клиент-серверных приложений уровня корпорации.

Средства и технологии, используемые в статье:

  • ADO .Net 2.0
  • Data Protection API (DAPI)
  • Visual Studio 2005 Professional
  • Firebird SQL Server 2.0
  • IBProvider v.3 и IBProvider v.2

Что такое OLE DB Provider?

Для доступа к базам данных в ADO (а теперь эта возможность есть и в ADO.Net) используются OLE DB провайдеры. Ole Db Provider представляет собой драйвер для доступа к базе данных при помощи OLE DB интерфейсов. Для взаимодействия с OLE DB провайдером в .Net реализовано пространство имен System.Data.OleDb.

При работе с Firebird я использую IBProvider (www.ibprovider.com) и в своем повествовании буду опираться, прежде всего, на его функциональность. Разработчики IBProvider поддерживают три коммерческих версии драйвера. Так же есть бесплатная. Для написания примеров применялся IBProvider третьей версии и только для примера управляющих ODBC последовательностей использовался IBProvider v2.

Список основных различий в версиях IBProvider:

Возможности IBProvider Free IBProvider v1/IBProvider v2 IBProvider v3
Поддержка всей линейки серверов Interbase, Yaffil, Firebird, включая FB2 да да да
Возможность работы с ADO и соответственно с Microsoft Office, VBA, VBScript, Java Script и др. да да да
Отсутствие ограничений на размер получаемых данных да да да
Поддержка ADO.Net нет да да
Возможность работы в качестве MS SQL Linked Server нет да да
Работа с метаданными нет да да
Поддержка обновляемых множеств нет нет/да пока нет
Поддержка распределенных транзакций нет да да
Вложенные транзакции нет нет да
Поддержка управляющих последовательностей ODBC для SQL запросов (используется в Crystal Reports, MS SQL Server, различные OLAP и др. инструменты) нет да пока нет
Поддержка DDL запросов да, но без поддержки SQL парсером провайдера да да
Тип закладок 4 байта 4 байта/8 байт 8 байт
Поддержка Client Cursor Engine нет да да
Уведомления о завершении транзакции нет нет да
Предоставление расширенной информации о сервере (версия, тип сервера, размер страницы). нет да да
Возможность задавать используемую клиентскую библиотеку (gds32.dll или fbclient.dll) нет нет да
Поддержка изменений в DML (Data Model Language) для Firebird 2 нет нет да
Новые свойства и алгоритмы Firebird 2 (возможность узнать дату создания базы и т.п.) нет нет да

Наиболее современным решением является IBProvider третьей версии. В его основе лежит абсолютно новое ядро и в нем реализованы технологии управления данными, которые явились результатом 5-тилетних исследований в данной области, а так же вобрали в себя опыт разработки крупных программных проектов и библиотек доступа к данным. На момент написания статьи в третьей версии не была реализована технология обновляемых множеств, а так же не поддерживались управляющие последовательности ODBC. Но, насколько мне известно, поддержка ODBC Escape Sequences уже планируется разработчиками в ближайших версиях провайдера.

Методы подключения к базе данных

Параметры строки подключения

Для использования Ole Db провайдера необходимо подключить соответствующее пространство имен к нашему проекту:

using System.Data.OleDb;

Управление подключением к Ole Db источникам данных осуществляется с помощью класса OleDbConnection. Самый простой способ подключения к базе данных – прямое указание строки подключения в конструкторе этого класса:

OleDbConnection con = new OleDbConnection(connectionString);            
con.Open();
con.Close();

Для формирования строки подключения в Net 2.0 появился класс OleDbConnectionStringBuilder:

OleDbConnectionStringBuilder cb = new OleDbConnectionStringBuilder();
cb.Provider = "LCPI.IBProvider";            
cb.Add("Location",@"localhost:d:\Program Files\Firebird\examples\EMPLOYEE.FDB");
cb.Add("User ID", "sysdba");
cb.Add("Password", "masterkey");
cb.Add("ctype", "win1251");
Console.WriteLine(cb.ToString())

Существует определенный набор свойств инициализации IBProvider-a, который необходимо установить перед выполнением соединения с БД:

Обязательные свойства инициализации (параметры подключения) IBProvider:

Свойство Описание
Location Путь к базе данных на сервере.
Provider Имя Ole Db провайдера
User ID Имя пользователя базы данных
Password Пароль пользователя
Ctype Кодировка определяет, символы какого национального алфавита будут использоваться. Для русского и английского алфавита можно использовать кодировку WIN1251

Некоторые необязательные свойства инициализации IBProvider:

Свойство Описание
Data Source Данное свойство используется для задания user friendly имени для базы данных, например "Employee DB". Если свойство Loсation не определено, то предполагается, что в Data Source указано расположение базы данных.
db_client_type Тип клиента сервера базы данных. Есть только в IBProvider v3.
db_client_library DLL с клиентом сервера
auto_commit Режим автоматического подтверждения транзакций. Для его включения в строке подключения необходимо указать “auto commit =true”.
role Роль пользователя

Более подробно о свойствах инициализации IBProvider-а можно прочитать здесь

СОВЕТ.  Всегда включайте в параметр Location имя сервера базы данных. Это позволит обеспечить совместимость со всем версиями Firebird
Способы хранения строк подключения
В реальных приложениях никто не прописывает строки подключения к базе данных в коде. Гораздо эффективнее использовать для этой цели либо настройки приложения (технология Settings), либо отдельный файл подключения.

Для хранения параметров подключения в Windows существует специальный тип файлов Microsoft Data Link – это файл с расширением udl. С этим расширением ассоциирован универсальный редактор подключений. IBProvider поддерживает свои собственные табы, которые предоставляют удобный интерфейс для формирования параметров соединения. Для того чтобы использовать udl файл в своем приложении, выполните следующие шаги:

  • Создайте пустой файл с расширением .udl
  • Откройте файл (Enter), появится связанный с данным расширением диалог для настройки подключения:
  • В списке OleDb провайдеров выберете IBProvider v3:

datalink1.gif

  • Задайте параметры подключения по аналогии с рисунком и нажмите кнопку «Проверить подключение»:

datalink2.gif

  • На вкладке дополнительно вы можете задать расширенные свойства подключения:

datalink3.gif

  • Нажмите «Ок» для записи информации о подключении в файл

Теперь для того, чтобы использовать подключение, описанное udl файлом, достаточно явно или через OleDbConnectionStringBuilder задать свойство File Name

OleDbConnectionStringBuilder cb = new OleDbConnectionStringBuilder();
cb.FileName = AppDomain.CurrentDomain.BaseDirectory + @"\employee.udl";
OleDbConnection con = new OleDbConnection(cb.ToString());
con.Open();

Второй способ хранения строки подключения – это поместить её в конфигурационный файл приложения:

В свойствах проекта выберите вкладку Settings и создайте новое свойство с именем ConnectionString и типом (Connection string):

datalinkIDE_CreateSetting.gif

При редактировании свойства запустится встроенный в VS 2005 редактор строки подключения:

datalinkIDE.gif



ПРИМЕЧАНИЕ.   Если нажать на кнопку “Data Links”, то появится уже знакомый нам диалог конфигурации Microsoft Data Link

Для того, чтобы прочитать строку подключения из файла конфигурации, необходимо создать экземпляр класса настроек вашего приложения:

Properties.Settings s = new Properties.Settings();
//чтение свойства с именем ConnectionString
Console.WriteLine(s.ConnectionString); 

Для облегчения написания примеров был создан класс ConnectionProvider, который инкапсулирует в себе все, описанные методы подключения.

Шифрование строки подключения. Data Protection API
Один из вариантов защитить строку подключения в своем конфигурационном файле - это воспользоваться Data Protection API (DAPI). Начиная с Windows 2000, DAPI является частью операционной системы.

Допустим, нам необходимо зашифровать данные, хранящиеся в секции connectionStrings. Для этого мы воспользуемся классом DataProtectionConfigurationProvider:

Подключим к нашему проекту сборку System.Configuration.dll и используем следующий код:

public void DataProtectionAPITest()
{
    try
    {          
    //открываем секцию connectionStrings из App.config               
    Configuration config = ConfigurationManager.OpenExeConfiguration(
    System.Reflection.Assembly.GetExecutingAssembly().Location);

    ConnectionStringsSection section =
    config.GetSection("connectionStrings") as ConnectionStringsSection;

    if (!section.SectionInformation.IsProtected)
       {
         // выполняем шифрование секции
         section.SectionInformation.ProtectSection(
         "DataProtectionConfigurationProvider");
         // Сохраняем конфигурацию
         config.Save();
       }

    }
    catch (Exception ex)
    {
           Console.WriteLine(ex.Message);
    }

    // получаем строку подключения из зашифрованной секции
    Console.WriteLine(Properties.Settings.Default.ConnectionString);
}  
ПРЕДУПРЕЖДЕНИЕ.   Данные, хранящиеся в секции, могут быть расшифрованы только на том компьютере, на котором были зашифрованы. Таким образом, процедуру шифрования данных необходимо вызывать на компьютере конечного пользователя.

Данный пример как раз подходит для этих целей. При установке приложения мы помещаем в папку с программой ещё не зашифрованный App.Config. При первом запуске приложения данная процедура его зашифрует и, в последствии, программа будет работать уже с защищенной секцией. Можно так же вызывать процедуру шифрования во время установки приложения.

К сожалению, нет стандартных средств для защиты UDL файлов, поэтому стоит воспользоваться способом хранения защищенных строк подключения в файле конфигурации.

Команды

Команды предназначены для передачи запросов базе данных. Для Ole Db провайдеров команда реализуется классом OleDbCommand. Команда всегда выполняется для заданного открытого подключения к базе данных в контексте транзакции.

Для того чтобы выполнить запрос к базе данных необходимо выполнить следующую последовательность действий:

  • Создать подключение к БД и открыть его
  • Создать активную транзакцию из текущего подключения – метод OleDbConnection.BeginTransaction()
  • Создать объект OleDbCommand, либо используя один из вариантов перегруженного конструктора, либо метод OleDbConnection.CreateCommand()
  • Установить свойство команды Transaction, если оно не было задано в конструкторе
  • Задать текст команды CommandText
  • Для обращения к базе данных у команды есть три метода ExecuteScalar, ExecuteReader и ExecuteNonQuery.
  • Завершить транзакцию OleDbTransaction.Commit() или откатить OleDbTransaction.Rollback() и закрыть подключение.
ExecuteScalar

Возвращает единственное значение первой колонки первой строки. Остальные результаты игнорируются. Этот метод полезен для запросов, которые, к примеру, считают количество записей в таблице – соответственно возвращают только одно значение:

public void ExecuteScalarTest()
{
   OleDbConnection con = ConnectionProvider.CreateConnection();
   con.Open();
   OleDbTransaction trans = con.BeginTransaction();

   OleDbCommand cmd = new OleDbCommand("select count(*) from employee", con, trans);   
   Console.WriteLine("Record count:" + cmd.ExecuteScalar().ToString());
  
   trans.Commit();
   con.Close();  
}
ExecuteReader
Данный метод возвращает объект OleDbDataReader, который по своему назначению очень близок объекту Recordset из классического ADO. Он использует однонаправленное ForwardOnly чтение данных, реализуя подсоединенную модель доступа. Таким образом, при его использовании необходимо наличие открытого подключения к базе.

Навигация по строкам результирующего множества осуществляется при помощи метода Read(), который возвращает true в случае, если ещё остались строки и false в противном случае. При вызове метода команды ExecuteReader(), созданный им объект OleDbDataReader не спозиционирован на первой строке результирующего множества и для её прочтения необходимо сначала вызвать метод Read().

Наиболее удобным способом чтения данных из результирующего множества является использование метода Read() совместно с конструкцией while:

public void ExecuteReaderTest()
{
   OleDbConnection con = ConnectionProvider.CreateConnection();
   con.Open();
            
   //Испольуем метод CreateCommand для создания команды
   OleDbCommand cmd = con.CreateCommand();
   cmd.Transaction = con.BeginTransaction();
   cmd.CommandText = "select * from employee";            
   OleDbDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);

   //чтение данных
   while (rdr.Read())
   { 
      string tmp ="";
      for(int i=0; i<rdr.FieldCount -1;i++) 
      {
         if (tmp != "") tmp += "\t";
         tmp += rdr[i].ToString();
      }

      Console.WriteLine(tmp);  
   }

   rdr.Close();
   //после вызова OleDbDataReader.Close() подключение к БД будет закрыто     
   Assert.AreEqual(ConnectionState.Closed,con.State);  
}
ПРИМЕЧАНИЕ.   Обратите внимание, что после вызова метода OleDbDataReader.Close() подключение к базе данных будет закрыто. Это произошло потому, что я применил перегруженный метод ExecuteReader() с заданным параметром CommandBehavior.CloseConnection. По умолчанию после выполнения метода OleDbDataReader.Close() подключение к базе данных остается открытым
ExecuteNonQuery
Метод применяется для выполнения запросов, которые возвращают количество обработанных записей, таких как insert, update, delete, а так же для выполнения хранимых процедур, результат которых помещается в OUT параметры команды:
public void ExecuteNonQueryTest()
{
    OleDbConnection con = ConnectionProvider.CreateConnection();        
    con.Open();        
    OleDbTransaction trans = con.BeginTransaction();        

    //INSERT         
    OleDbCommand cmd = new OleDbCommand(        
    "insert into country (country,currency) values(:country,:currency) ", 
    con, trans);
            
    cmd.Parameters.AddWithValue("country", "Russia");
    cmd.Parameters.AddWithValue("currency", "Kopec");
           
    // количество обработанных строк
    Assert.AreEqual(1, cmd.ExecuteNonQuery());
 
    //UPDATE
    cmd = new OleDbCommand(
    "update country set currency=:currency where country =:country", con, trans);
            
    cmd.Parameters.AddWithValue("currency", "Rouble");
    cmd.Parameters.AddWithValue("country", "Russia");

    // количество обработанных строк
    Assert.AreEqual(1, cmd.ExecuteNonQuery());
       
    //DELETE
    cmd = new OleDbCommand(
    "delete from country where country =:country", con, trans);
            
    cmd.Parameters.AddWithValue("country", "Russia");

    // количество обработанных строк
    Assert.AreEqual(1, cmd.ExecuteNonQuery());

    trans.Commit();
    con.Close();  
}
Параметры команд

В большинстве случаев при выполнении команды требуется задать её параметры. Параметры добавляются в коллекцию Parameters. Они могут быть именованные и позиционные. Пример команды с позиционными параметрами:

insert into country (country,currency) values(?,?)

С именованными:

insert into country (country,currency) values(:country,:currency)

IBProvider сам умеет формировать список параметров, производя анализ SQL выражения. Но, к сожалению, в ADO .Net необходимо вручную добавлять эти параметры, т.к. команда не запрашивает их описание у Ole Db провайдера. Если вспомнить ADO, то в нем список параметров прекрасно формировался без необходимости вмешиваться в этот участок кода.

Для того, чтобы добавить параметр, нужно воспользоваться:

  • для добавления именованного параметра и значения - методом AddWithValue()
  • для добавления как именованных, так и неименованных параметров - перегруженным методом Add()

Если не указан тип параметра, он будет добавлен с Ole Db типом VarWChar, что соответствует .Net типу string, что кажется разумным. Об этом не стоит беспокоиться, т.к. IBProvider корректно обрабатывает приведение любых типов Firebird.

Нельзя не сказать о существующих ограничениях при использовании именованных параметров совместно с OleDbCommand. В MSDN написано, что именованные параметры поддерживаются только для поставщиков данных MSSQL и Oracle, а для поставщиков данных Ole Db и ODBC поддерживаются только позиционные параметры. Использовать именованные параметры все же можно, но их добавление в коллекцию Parameters необходимо осуществлять в том же порядке, в каком они следуют в запросе. К примеру, если текст команды:

update country set currency=:currency where country =:country 

то сначала необходимо добавить параметр currency, а потом country:

cmd.Parameters.AddWithValue("currency", "Rouble");
cmd.Parameters.AddWithValue("country", "Russia");

Задавать значения параметров можно уже в произвольном порядке:

cmd.Parameters["country"].Value = "Latvia";
cmd.Parameters["currency"].Value = "Lat";
Вызов хранимых процедур
Существуют два способа обработки результатов хранимых процедур:
  • хранимая процедура возвращает результирующее множество
  • результат выполнения хранимой процедуры помещается в OUT параметры команды

Для первого способа используется обычная SQL-инструкция:

 select * from stored_procedure_name(…)

Результат её выполнения обрабатывается при помощи объекта OleDbDataReader:

public void StoredProcedureResultSetTest()
{
   OleDbConnection con = ConnectionProvider.CreateConnection();
   con.Open();
   OleDbTransaction trans = con.BeginTransaction();

   //select stored procedure in params 
   OleDbCommand cmd_in_params = 
new OleDbCommand("select cust_no from CUSTOMER", con, trans);
      
  //select mail label through the stored procedure
  OleDbCommand cmd_stored_proc = 
new OleDbCommand("select * from mail_label(:cust_no)", con, trans);
  
  //add one IN parameter                     
  cmd_stored_proc.Parameters.Add("cust_no", OleDbType.Integer);

  //execure reader
  using (OleDbDataReader rdr = cmd_in_params.ExecuteReader(CommandBehavior.CloseConnection))
  {
     //for each customer No  
     while (rdr.Read())
     {                    
        cmd_stored_proc.Parameters["cust_no"].Value = rdr["cust_no"];
        using (OleDbDataReader rdr_out = cmd_stored_proc.ExecuteReader())
        {
           Console.WriteLine("Customer №" + rdr["cust_no"]);                   
           while (rdr_out.Read())
                  for (int i = 0; i < rdr_out.FieldCount; i++)
                    Console.WriteLine(rdr_out.GetName(i) + "=" + rdr_out[i]);

           Console.WriteLine();
        }
                    
     }

  }
}

Второй способ – вызов хранимой процедуры через инструкцию:

 execute procedure stored_procedure_name

Результат выполнения помещается в OUT параметры команды, которые предварительно необходимо создать:

public void StoredProcedureOUTParamsTest()
{
   OleDbConnection con = ConnectionProvider.CreateConnection();
   con.Open();
   OleDbTransaction trans = con.BeginTransaction();

   //select in params 
   OleDbCommand cmd_in_params =
     new OleDbCommand("select cust_no from CUSTOMER", con, trans);

   //STORED PROCEDURE
   OleDbCommand cmd_stored_proc = 
     new OleDbCommand("execute procedure mail_label(:cust_no)", con, trans);

   //IN parameter
   cmd_stored_proc.Parameters.Add("cust_no", OleDbType.BSTR);
   //OUT parameters
   cmd_stored_proc.Parameters.Add("line1", OleDbType.BSTR)
                   .Direction = ParameterDirection.Output;         
   cmd_stored_proc.Parameters.Add("line2", OleDbType.BSTR)
                   .Direction = ParameterDirection.Output;
   cmd_stored_proc.Parameters.Add("line3", OleDbType.BSTR)
                   .Direction = ParameterDirection.Output;
   cmd_stored_proc.Parameters.Add("line4", OleDbType.BSTR)
                   .Direction = ParameterDirection.Output;
   cmd_stored_proc.Parameters.Add("line5", OleDbType.BSTR)
                   .Direction = ParameterDirection.Output;
   cmd_stored_proc.Parameters.Add("line6", OleDbType.BSTR)
                    .Direction = ParameterDirection.Output;

   //execure reader
   using (OleDbDataReader rdr = cmd_in_params.ExecuteReader())
   {
       //for each customer No  
       while (rdr.Read())
       {
         cmd_stored_proc.Parameters["cust_no"].Value = rdr["cust_no"];
         cmd_stored_proc.ExecuteNonQuery();

         Console.WriteLine("Customer №" + rdr["cust_no"]);
         Console.WriteLine(cmd_stored_proc.Parameters["line1"].Value);
         Console.WriteLine(cmd_stored_proc.Parameters["line2"].Value);
         Console.WriteLine(cmd_stored_proc.Parameters["line3"].Value);
         Console.WriteLine(cmd_stored_proc.Parameters["line4"].Value);
         Console.WriteLine(cmd_stored_proc.Parameters["line5"].Value);
         Console.WriteLine(cmd_stored_proc.Parameters["line6"].Value);
         Console.WriteLine("");
       }
   }

   trans.Commit();
   con.Close();
}
Работа с массивами
ADO .Net может работать с любыми типами данных. Для тех типов Ole Db, у которых нет прямого отображения на типы данных .Net, используется тип данных DBTYPE_VARIANT. Массивы относятся как раз к таким типам.

Следующий пример демонстрирует чтение и запись массива из 5 элементов:

public void ArrayReadWriteTest()
{
    OleDbConnection con = ConnectionProvider.CreateConnection();
    con.Open();
    OleDbTransaction trans = con.BeginTransaction();

    OleDbCommand cmd = new OleDbCommand(
    "select job_code, job_grade, job_country, job_title, language_req from job", 
    con, trans);

    OleDbCommand cmd_upd = new OleDbCommand(
    "update job set language_req=:language_reg where \n" +
    "job_code=:job_code and job_grade=:job_grade and job_country=:job_country", 
    con, trans);

    cmd_upd.Parameters.Add("language_req", OleDbType.Variant);
    cmd_upd.Parameters.Add("job_code", OleDbType.BSTR);
    cmd_upd.Parameters.Add("job_grade", OleDbType.BSTR);
    cmd_upd.Parameters.Add("job_country", OleDbType.BSTR);

    using (OleDbDataReader rdr = cmd.ExecuteReader())
    {
        while (rdr.Read())
        {
        Console.WriteLine("JOB TITLE:" + rdr["job_title"].ToString());

        //чтение массива
        object lang_obj_arr = rdr["language_req"];

        if (lang_obj_arr != DBNull.Value)
        {
            //преобразование к массиву
            //используем Array.CreateInstance для создания массива
        //из 5 элементов, с адресацией начиная с 1-го элемента, а не с 0            
        short arr_lower_bound = 1;

            Array lang_str_arr = Array.CreateInstance(typeof(string), new int[] {5}, new int[] { arr_lower_bound }); 

            //копирование элементов в массив                         
            ((Array)lang_obj_arr).CopyTo(lang_str_arr, arr_lower_bound);

            for (int i = arr_lower_bound; i < lang_str_arr.Length + arr_lower_bound; i++)
            {
              //усечение символа \n на концах элементов массива
  	   string trimmed_value =    
  		   lang_str_arr.GetValue(i).ToString().Replace("\n", "");
              lang_str_arr.SetValue(trimmed_value, i);

              //вывод значения
              if (lang_str_arr.GetValue(i).ToString() != "")
                  Console.WriteLine(lang_str_arr.GetValue(i));
            }

            //запись новых значений элементов массива без символа \n                       
            cmd_upd.Parameters["language_req"].Value = lang_str_arr;
            cmd_upd.Parameters["job_code"].Value = rdr["job_code"];
            cmd_upd.Parameters["job_grade"].Value = rdr["job_grade"];
            cmd_upd.Parameters["job_country"].Value = rdr["job_country"];
        
            //передача изменений в БД
            Assert.IsTrue(cmd_upd.ExecuteNonQuery() == 1);    
         }
         else
            Console.WriteLine("No language specified");

         Console.WriteLine("");
       }
   }

   //откат сделанных изменений         
   trans.Rollback();
   con.Close();
}
ПРИМЕЧАНИЕ.   В примере использован базовый класс Array и метод CreateInstance для создания массива строк. В C# адресация массивов начинается с нулевого элемента, а в данном случае в базе данных записан массив, который проиндексирован, начиная с первого элемента. Array.CreateInstance() позволяет указать нижнюю границу массива элементов. В случае массивов с нулевой адресацией достаточно использования типизированных наследников класса Array, например string[], int[] и т.д.
Работа с BLOB полями

IBProvider поддерживает работу с двумя типами BLOB полей: содержащих текст и бинарные данные. Не могу не заметить, что при использовании этого провайдера работа с BLOB полями происходит так же, как и с обычными типами данных:

public void BLOBReadWriteTest()
{
    OleDbConnection con = ConnectionProvider.CreateConnection();
    con.Open();
    OleDbTransaction trans = con.BeginTransaction();

    //BLOB Read command
    OleDbCommand cmd = new OleDbCommand(
    "select proj_id, proj_name,proj_desc from project", con, trans);

    //BLOB write command			
    OleDbCommand cmd_update = new OleDbCommand(
    "update project set proj_desc=:proj_desc where proj_id=:proj_id", con, trans);
	
    //create parameters with BSTR type
    cmd_update.Parameters.Add("proj_desc", OleDbType.BSTR);
    cmd_update.Parameters.Add("proj_id", OleDbType.BSTR);

    using (OleDbDataReader rdr = cmd.ExecuteReader())
    {
       while (rdr.Read())
       {
		 //чтение BLOB 
             Console.WriteLine("PROJECT: " + rdr["proj_name"].ToString());
             Console.WriteLine(rdr["proj_desc"].ToString());

             //запись BLOB
             cmd_update.Parameters["proj_id"].Value = rdr["proj_id"];

             //каждый раз меняем регистр данных в BLOB поле
             string new_project_description = rdr["proj_desc"].ToString();
             if (new_project_description.ToUpper() != new_project_description)
                 new_project_description = new_project_description.ToUpper();
             else
                 new_project_description = new_project_description.ToLower(); 

             cmd_update.Parameters["proj_desc"].Value = new_project_description;
             Assert.AreEqual(1, cmd_update.ExecuteNonQuery());            
  	    }
    }

    trans.Commit();			
    con.Close();
}

Здесь тип параметров команды обновления установлен в OleDbType.BSTR. В этом случае провайдер корректно распознает тип параметров и произведет их преобразование к типам базы данных.

СОВЕТ.   В примере OleDbDataReader использован совместно с конструкцией using. Он поддерживает интерфейс IDispose и после завершения работы сам позаботится о своем закрытии, а если в метод OleDbCommand.ExecuteReader() передать значение CommandBehavior.CloseConnection, то так же будет закрыто подключение к базе данных.
MARS - Multiple Active Result Sets

В ADO .Net 2.0 появилась «новая» технология, которая получила название MARS. В Net Framework 1.1. в одном контексте транзакции было невозможно держать открытый OleDbDataReader и параллельно выполнять дополнительные запросы к базе данных или открывать ещё один OleDbDataReader. При попытке выполнить этот трюк мы получали исключение вида:

«There is already an open DataReader associated with this Connection which must be closed first.»

Предыдущий пример работы с BLOB полями как раз и показывает применение технологии MARS. В нем демонстрируется последовательное чтение данных и их одновременное их обновление.

Если обратиться к истории, то мы обнаружим, что технология эта совсем не новая, да и технологией назвать это сложно. Если сравнить вторую версию ADO .Net с первой, то, конечно, разработчики добились определенных успехов. Но возможность использовать несколько RecordSet в одной транзакции была реализована ещё в классическом ADO. Скажу больше, там можно было использовать несколько RecordSet, связанных с одной командой. Это достигалось за счет клонирования команды внутри себя, если обнаруживалось, что уже есть связанное с ней множество. В ADO .NET команда тоже умеет клонировать саму себя. Для этого есть метод Clone(), который необходимо вызывать явно, если вы хотите связать несколько OleDbDataReader с одной командой.

Таким образом, применение MARS возможно не только для MS SQL Server, как пишут во многих источниках информации, но и для других баз данных.


Далее

Размещение рекламы — тел. +7 495 4119920, ICQ 232284597

Подписка на новости IT-портала CITForum.ru
(библиотека, CITKIT.ru, CitCity)

Новые публикации:

24 декабря

CITKIT.ru:

  • Новогодние поздравления
  • Сергей Кузнецов. Цикл Операционные системы: Ностальгия по будущему:

  • Алексей Федорчук. OpenSolaris 2008.11 Release

  • Сергей Голубев:

  • Евгений Чайкин aka StraNNik (Блогометки):

    17 декабря

  • С.Д.Кузнецов. Базы данных. Вводный курс

    10 декабря

    CITKIT.ru:

  • OpenSolaris 2008.11 Release

  • Альтернативные ОС: две грустные истории (С.Кузнецов)
  • Nokia N810 — доведение до ума
  • CitCity:

  • Платформа 2009: заоблачные перспективы Microsoft

    4 декабря

  • Лекция С.Д.Кузнецова Понятие модели данных. Обзор разновидностей моделей данных

    CITKIT.ru:

  • OpenSolaris 2008.11 Release. Первые впечатления

  • Linux vs FreeBSD: продолжим "Священные войны"?

  • Nokia N810 as is

  • Индульгенция для FOSS

  • Друзья СПО'2008

    26 ноября

  • Нечеткое сравнение коллекций: семантический и алгоритмический аспекты

    CitCity:

    CITKIT.ru:

  • Глава из книги А.Федорчука
    Сага о FreeBSD:
  • 19 ноября

  • Проблемы экономики производства крупных программных продуктов

  • Язык модификации данных формата XML функциональными методами

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

    Заметки к книге:

  • FreeBSD: монтирование сменных устройств и механизм HAL
  • Текстовый редактор ee

    12 ноября

  • Правило пяти минут двадцать лет спустя, и как флэш-память изменяет правила (Гоц Грейф, перевод: Сергей Кузнецов)

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:
  • OSS в России: взгляд правоведа (В.Житомирский)

  • Новая статья из цикла С.Голубева "Железный марш":

    29 октября

  • О некоторых задачах обратной инженерии

  • Веб-сервисы и Ruby

  • Тестирование web-приложений с помощью Ruby

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

  • PuppyRus Linux - беседа с разработчиком (С.Голубев)

  • Сергей Кузнецов. Заметка не про Linux

    22 октября

  • Обзор методов описания встраиваемой аппаратуры и построения инструментария кросс-разработки

    CITKIT.ru:

  • Сергей Кузнецов. Почему я равнодушен к Linux

  • Глава из книги А.Федорчука
    Сага о FreeBSD:
  • Что надо иметь
    3. Базовые познания

    CitCity:

  • Управление IT-инфраструктурой на основе продуктов Microsoft

    15 октября

  • Методы бикластеризации для анализа интернет-данных

    CitCity:

  • Разъемы на ноутбуках: что они дают и зачем их так много?
  • AMD Puma и Intel Centrino 2: кто лучше?

    CITKIT.ru:

  • Новый цикл статей С.Голубева
    Железный марш:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

    8 октября

  • Автоматизация тестирования web-приложений, основанных на скриптовых языках
  • Опыт применения технологии Azov для тестирования библиотеки Qt3

    Обзоры журнала Computer:

  • SOA с гарантией качества
  • Пикоджоуль ватт бережет
  • ICT и всемирное развитие

    CitCity:

  • Пиррова победа корпорации Microsoft

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

    Статья из архива:

  • Я живу в FreeBSD (Вадим Колонцов)

    Новые Блогометки:

  • Перекройка шаблона Blogger или N шагов к настоящему
  • Blogger. Comment style
  • Screenie или глянцевый снимок экрана

    2 октября

    CITKIT.ru:

  • Сага о FreeBSD (А. Федорчук)

    Zenwalk: пакет недели

  • Банинг — интеллектуальное развлечение (С.Голубев)

    CitCity:

    25 сентября

  • Клермонтский отчет об исследованиях в области баз данных

    CITKIT.ru:

  • Пользователям просьба не беспокоиться... (В.Попов)

  • Снова про ZFS: диск хорошо, а два лучше
  • Командная оболочка tcsh (А.Федорчук)

    Zenwalk: пакет недели

    17 сентября

  • T2C: технология автоматизированной разработки тестов базовой функциональности программных интерфейсов
  • Технология Azov автоматизации массового создания тестов работоспособности

    CITKIT.ru:

  • FreeBSD: ZFS vs UFS, и обе-две — против всех (А.Федорчук)

    Zenwalk: пакет недели

  • Дачнет — практика без теории (С.Голубев)

    10 сентября

  • За чем следить и чем управлять при работе приложений с Oracle
  • Планировщик заданий в Oracle
    (В.Пржиялковский)

    CITKIT.ru:

  • Microsoft: ответный "боян" (С.Голубев)

  • Причуды симбиоза, или снова "сделай сам" (В.Попов)

  • Файловые системы современного Linux'а: последнее тестирование
  • Zsh. Введение и обзор возможностей
    (А.Федорчук)

    Описания пакетов Zenwalk: Zsh, Thunar, Thunar-bulk-rename, Xfce4-places-plugin, Xfce4-fsguard-plugin

    Блогометки:

  • Google Chrome
  • Лончер для ASUS Eee PC 701

    3 сентября

    CITKIT.ru:

  • Заметки о ядре (А.Федорчук):

    Добавлены описания пакетов Zenwalk: Galculator, Screenshot, Gnumeric, Pidgin

    В дискуссинном клубе:

  • И еще о Википедии и Google Knol

  • Лекция для начинающего линуксоида (С.Голубев)

    26 августа

  • Транзакционная память (Пересказ: С. Кузнецов)

    CITKIT.ru:

  • Открыт новый проект Zenwalk: пакет недели

  • Статья Текстовые процессоры и их быстродействие: конец еще одной легенды?

    21 августа

    CITKIT.ru:

  • Почему школам следует использовать только свободные программы (Ричард Столлман)
  • Беседа Сергея Голубева с учителем В.В.Михайловым

  • Википедия или Гуглезнание? Приглашение к обсуждению (Алексей Федорчук)
  • Народная энциклопедия от Google (StraNNik)

  • Обзор Mandriva 2009.0 Beta 1 Thornicrofti
  • Новичок в Линукс: Оптимизируем Mandriva 2008.1

  • Книга Zenwalk. Приобщение к Linux:

    13 августа

    CitCity:

  • Мирный Atom на службе человеку. Обзор платы Intel D945GCLF с интегрированным процессором
  • Обзор процессоров Intel Atom 230 на ядре Diamondville

  • iPhone - год спустя. Скоро и в России?

    CITKIT.ru:

  • Интермедия 3.4. GRUB: установка и настройка (из книги Zenwalk. Приобщение к Linux)

    6 августа

  • СУБД с хранением данных по столбцами и по строкам: насколько они отличаются в действительности? (Пересказ: С. Кузнецов)

    CITKIT.ru:

  • Интермедия 2.2. Что неплохо знать для начала (из книги Zenwalk. Приобщение к Linux)

  • И снова про шрифты в Иксах (А.Федорчук)

  • 20 самых быстрых и простых оконных менеджеров для Linux

  • Дело о трех миллиардах (С.Голубев)

    30 июля

  • OLTP в Зазеркалье (Пересказ: С. Кузнецов)

    CitCity:

  • Будущее BI в облаках?
  • Тиражные приложения и заказная разработка. Преимущества для заказчика
  • Дискуссия со сторонниками заказной разработки

    CITKIT.ru:

  • Новые главы книги Zenwalk. Приобщение к Linux:
  • Глава 8. Пакеты: средства установки, системы управления, системы построения
  • Глава 9. Zenwalk: репозитории, пакеты, методы установки

    23 июля

    CITKIT.ru:

  • Все против всех. 64 vs 32, Intel vs AMD, tmpfs vs ext3
  • Две головы от Intel

  • Zenwalk: обзор штатных приложений (глава из книги "Zenwalk. Приобщение к Linux")

  • Нормально, Григорий...

    16 июля

    Обзоры журнала Computer:

  • Перспективы и проблемы программной инженерии в XXI веке
  • Большие хлопоты с большими объемами данных
  • Перспективы наноэлектроники

    CITKIT.ru:

  • Интермедия о лицензиях (А.Федорчук. "Zenwalk. Приобщение к Linux")

  • Есть ли будущее у KDE?

  • Linux в школе: альтернативный вариант в задачах

  • Шифр (приключения агента Никодима)

    10 июля

    CITKIT.ru:

  • Новые разделы книги А. Федорчука Zenwalk. Приобщение к Linux:
  • Интермедия вступительная. Linux или GNU/Linux? Как вас теперь называть?
  • Глава 5. Среда Xfce
  • Глава 6. Xfce: приложения и плагины

  • ZUR (Zenwalk User Repository) FAQ

    2 июля

  • Персистентность данных в объектно-ориентированных приложениях (С. Кузнецов)

    CITKIT.ru:

  • Новые разделы книги А. Федорчука Zenwalk. Приобщение к Linux:
  • Интермедия 1.2. Дорога к Zenwalk'у. Период бури и натиска
  • Интермедия 3.3. Немного о Linux'е и "железе"
  • Глава 4. Настройка: инструментами и руками
  • Интермедия 4.1. Zenpanel и конфиги: поиски корреляции

  • Интервью с Жан-Филиппом Гийоменом, создателем дистрибутива Zenwalk

  • Linux в школе: первые итоги (С. Голубев)

    25 июня

    CITKIT.ru:

  • Zenwalk. Приобщение к Linux (А. Федорчук)

  • Логика и риторика (С.Голубев)

  • Технология Tru64 AdvFS

  • Ханс Райзер предлагает отвести полицейских к телу Нины

    18 июня

  • Проекты по управлению данными в Google (Пересказ: С. Кузнецов)

    CITKIT.ru:

  • ОС и поддержка "железа": мифы и реальность (А. Федорчук)

  • Linux в школе: другие дистрибутивы

  • Пинок (С. Голубев)

    4 июня

  • Ландшафт области управления данными: аналитический обзор (С. Кузнецов)

    CITKIT.ru:

  • Linux в школе: слово заинтересованным лицам

  • SlackBuild: пакеты своими руками

  • Linux от компании Novell. Установка и обзор openSUSE Linux

    Все публикации >>>




  • IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

    Информация для рекламодателей PR-акции, размещение рекламы — тел. +7 495 4119920, ICQ 232284597 Пресс-релизы — pr@citcity.ru
    Послать комментарий
    Информация для авторов
    Rambler's Top100 TopList liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня This Web server launched on February 24, 1997
    Copyright © 1997-2000 CIT, © 2001-2007 CIT Forum
    Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...