Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
VPS/VDS серверы. 30 локаций на выбор

Серверы VPS/VDS с большим диском

Хорошие условия для реселлеров

4VPS.SU - VPS в 17-ти странах

2Gbit/s безлимит

Современное железо!

Бесплатный конструктор сайтов и Landing Page

Хостинг с DDoS защитой от 2.5$ + Бесплатный SSL и Домен

SSD VPS в Нидерландах под различные задачи от 2.6$

✅ Дешевый VPS-хостинг на AMD EPYC: 1vCore, 3GB DDR4, 15GB NVMe всего за €3,50!

🔥 Anti-DDoS защита 12 Тбит/с!

2006 г.

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

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

НазадСодержание

Отсоединенная модель. DataSet

Заполнение объекта DataSet

Класс DataSet служит для хранения данных, загруженных из базы, в памяти. Фактически он представляет собой набор таблиц, связанных отношениями и в идеальном случае копирует структуру исходной базы данных.

Он позволяет существенно сократить количество обращений к базе данных. Это особенно критично для WEB-приложений, для которых частое подключение к базе данных не является оптимальным.

Существуют несколько способов заполнения объекта DataSet:

Первый из них, который появился ещё в Net Framework 1.0, это способ заполнения DataSet при помощи класса OleDbDataAdapter:

public void FillDataSetFromDataAdapter()
{
   DataSet ds = new DataSet();

   using (System.Transactions.TransactionScope scope =
 		new System.Transactions.TransactionScope())
   {
      OleDbConnection con = ConnectionProvider.CreateConnection();
      con.Open();
                                
      OleDbDataAdapter adapter = 
           new OleDbDataAdapter("select * from EMPLOYEE", con);
      adapter.Fill(ds);

      Assert.IsTrue(ds.Tables[0].Rows.Count > 0);   
      scope.Complete();  
   }
}

Второй способ появился только в ADO .Net 2.0 – это возможность заполнения DataSet, используя OleDbDataReader:

public void FillDataSetFromDBReaderTest()
{
    OleDbConnection con = ConnectionProvider.CreateConnection(); 
    con.Open();
    OleDbCommand cmd =
      new OleDbCommand("select * from EMPLOYEE",con,   con.BeginTransaction()); 

    DataSet ds = new DataSet();
    DataTable tbl = ds.Tables.Add("EMPLOYEE");

    using (OleDbDataReader reader = 
                           cmd.ExecuteReader(CommandBehavior.CloseConnection))
    {
          ds.Load(reader, LoadOption.OverwriteChanges, tbl); 
    }
}
DataTableReader

Данный класс позволяет использовать объект DataTable в режиме однонаправленного ForwardOnly чтения. Он, так же как и OleDbDataReader, наследуется от базового класса DBDataReader. Этот способ чтения таблиц DataSet может быть полезен, когда используются общие методы для отсоединенного источника данных и данных, которые формируются методом OleDbCommand.ExecuteReader() в подсоединенном режиме. Следующий пример демонстрирует использование общего метода PrintDBDataReader() для подсоединенного и отсоединенного режимов работы:

public void GetDBReaderFromDataTable()
{
   DataSet ds = new DataSet();
   DataTable tbl = ds.Tables.Add("EMPLOYEE");

   //загрузка данных в dataSet 
   OleDbConnection con = ConnectionProvider.CreateConnection();
   con.Open();
   OleDbTransaction trans = con.BeginTransaction();

   ds.Load(new OleDbCommand(
           "select * from EMPLOYEE",con,trans).ExecuteReader(),
           LoadOption.OverwriteChanges, tbl); 
            
   //используем DataTable в режиме однонаправленного чтения
   this.PrintDBDataReader(new DataTableReader(tbl));

   //OleDbDataReader и подсоединенный режим
   this.PrintDBDataReader(
        new OleDbCommand("select * from EMPLOYEE", con,  trans).ExecuteReader());

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

/// <summary>
/// Выводит в консоль данные из DBDataReader
/// </summary>
/// <param name="reader"></param>
public void PrintDBDataReader(System.Data.Common.DbDataReader reader)
{
     while (reader.Read())
     {
        Console.WriteLine("*********************************");
        for (int i = 0; i < reader.FieldCount; i++)
           Console.WriteLine(reader.GetName(i) + "=" + reader[i].ToString());
     }

     reader.Close(); 
}
Передача изменений обратно в базу данных

После того, как мы изменили данные в DataSet, их необходимо передать обратно в базу. Для этого у объекта OleDbDataAdapter есть метод Update(). Прежде чем его использовать, необходимо настроить наш адаптер. В этом нам поможет класс OleDbCommandBuilder. Он позволяет сгенерировать команды для операций вставки, обновления и удаления, а так же создать соответствующую коллекцию параметров команд. Ниже приведен пример передачи изменений из DataSet в базу данных:

public void UpdateDataSet()
{
   DataSet ds = new DataSet();
   DataTable tbl = ds.Tables.Add("EMPLOYEE");

   OleDbConnection con = ConnectionProvider.CreateConnection();
   con.Open();           
   OleDbDataAdapter adapter = new OleDbDataAdapter("select * from EMPLOYEE", con);
   adapter.SelectCommand.Transaction = con.BeginTransaction();
   adapter.Fill(tbl);

   //вносим изменения в DataSet
   foreach  (DataRow row in tbl.Rows)
      row["FIRST_NAME"] = row["FIRST_NAME"].ToString().ToUpper();

   //генерируем команды для операций update, insert и delete 
   OleDbCommandBuilder cmd_builder = new OleDbCommandBuilder(adapter);
   adapter.DeleteCommand = cmd_builder.GetDeleteCommand();
   adapter.UpdateCommand = cmd_builder.GetUpdateCommand();
   adapter.InsertCommand = cmd_builder.GetInsertCommand(); 
 
   //обновление данных
   adapter.Update(tbl); 

   //откат сделанных изменений
   adapter.SelectCommand.Transaction.Rollback();
   con.Close();  
}

Поддержка новых возможностей Firebird 2

Специальная поддержка DML (Data Manipulation Language)

Во второй версии Firebird появилось несколько нововведений. Одно из них это инструкция EXECUTE BLOCK. Она позволяет выполнить блок инструкций на стороне сервера, фактически это виртуальная хранимая процедура. Следующий пример демонстрирует использование ресурсов сервера базы данных для выполнения простого арифметического действия:

public void ExecuteBlockSQLTest()
{
    OleDbConnection con = OpenFB2Connection();
    OleDbTransaction trans = con.BeginTransaction();

    //текст команды
    string execute_block_data =
    "EXECUTE BLOCK (X INTEGER = :X) \n" +
    "RETURNS (Y INTEGER)           \n" +
    "AS                            \n" +
    "BEGIN                         \n" +
    "    Y = X * 2;                \n" +
    "SUSPEND;                      \n" +
    "END                           \n";

    //входящий параметр
    int in_parameter_X = 2;

    OleDbCommand cmd = new OleDbCommand(execute_block_data, con, trans);
    cmd.Parameters.AddWithValue("X", in_parameter_X);

    //выполнение команды EXECUTE BLOCK
    Assert.AreEqual((int)cmd.ExecuteScalar(), in_parameter_X * 2);
    trans.Commit();

    con.Close();
}

Еще одно новшество, которое подарил нам FB2, это инструкция INSERT RETURNING. Фактически она позволяет выполнить операцию вставки данных и прочитать значения, которые были добавлены в процессе этой операции. Это особенно актуально для получения значения идентификатора новой записи, для которого использовался генератор:

public void InsertReturning()
{
    OleDbConnection con = OpenFB2Connection();
    OleDbTransaction trans = con.BeginTransaction();

    //новая команда INSERT RETURNING 
    OleDbCommand cmd = new OleDbCommand(
    "insert into customer (cust_no, customer)     \n" +
    "values(GEN_ID(CUST_NO_GEN,1),:customer_name) \n" +
    "RETURNING cust_no",con,trans);

    cmd.Parameters.AddWithValue("customer_name", "New customer");
    //добавляем один выходной параметр
    cmd.Parameters.Add("customer_no", OleDbType.Integer)
 				.Direction =ParameterDirection.Output;
 
    Assert.AreEqual(1, cmd.ExecuteNonQuery());     

    //удаляем запись, используя значение генератора, полученного 
    //через INSERT .. RETURNING
    OleDbCommand cmd_delete = new OleDbCommand(
    "delete from customer where cust_no=?", con, trans);
       
    cmd_delete.Parameters.AddWithValue("?",cmd.Parameters["customer_no"].Value);
    Assert.AreEqual(1, cmd_delete.ExecuteNonQuery());

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

ROLLBACK RETAIN – позволяет откатить транзакцию на момент старта или до последнего вызова COMMIT_RETAIN, оставляя возможность её дальнейшего использования. Давайте рассмотрим это на примере:

public void RollbackRetainTest()
{
    OleDbConnection con = OpenFB2Connection();
    OleDbTransaction trans = con.BeginTransaction();

    //insert new record 
    OleDbCommand cmd = new OleDbCommand(
    "insert into customer (cust_no, customer)    " +
    "values(GEN_ID(CUST_NO_GEN,1),'new customer')", con, trans);
    Assert.AreEqual(1, cmd.ExecuteNonQuery());
    
    //ROLLBACK RETAIN 
    new OleDbCommand("ROLLBACK RETAIN", con, trans).ExecuteNonQuery();

    //transaction will be active and we can execute some command again
    cmd = new OleDbCommand(
        "select count(*) from customer", con, trans);
           
    Assert.IsTrue((int)cmd.ExecuteScalar() > 0 ); 

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

Ключевое слово ROWS соответствует последним стандартам ANSI SQL и является альтернативой FIRST/SKIP. Оно позволяет указать количество обрабатываемых записей. Может быть использовано в UNION, любых подзапросах, а так же в командах DELETE и UPDATE. Следующий пример читает из базы данных записи с первой по третью:

public void RowsKeywordTest()
{
      OleDbConnection con = OpenFB2Connection();
      OleDbTransaction trans = con.BeginTransaction();

      //command will return 3 records
      OleDbCommand cmd = new OleDbCommand(
      "select * from customer rows 1 to 3", con, trans);

      short rec_count = 0;

      using (OleDbDataReader reader = cmd.ExecuteReader())
          while (reader.Read()) { rec_count++; }

      Assert.AreEqual(3, rec_count);    

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

Я привел примеры только некоторых изменений в DML Firebird 2, которые требовали специальной поддержки со стороны Ole Db провайдера. Для изучения полного списка изменений рекомендую вам обратиться к документу: Firebird 2 release notes. Там действительно есть много того, что может заинтересовать разработчиков. Это производные таблицы, новые функции, улучшенный UNION, инструкция NEXT VALUE FOR, поддержка планов для операций обновления и удаления и много чего другого.

Другие изменения

Новое свойство источника данных «IB Database creation date» позволяет узнать дату создания базы данных. Прочитать его значение можно при помощи класса OleDbProperties, который подробно рассмотрен в разделе «Свойства объектов Ole Db»

Поддержка визуальных средств VS 2005

Встроенные инструменты Visual Studio 2005 могут оказаться незаменимым подспорьем при написании приложений баз данных. Давайте разберём по шагам создание примера простого приложения JobManager.

Создание подключения в Server Explorer

sampleWinforms_addCn1.gif

Выберем команду «Add Connection». Откроется диалог с выбором источника данных. В нем выбираем Data Source = <othrer> и Data provider = .Net Framework Data Provider for OLE DB. Жмем Ok:

sampleWinforms_addCn2.gif

Далее появится уже знакомый нам диалог:

sampleWinforms_addCn3.gif

Выберите из списка OleDb провайдеров – IBProvider третьей версии. И нажмите кнопку Data Links:

sampleWinforms_addCn4.gif

Здесь есть два важных момента: необходимо включить опции «Разрешить автоматические транзакции» и «Разрешить сохранение пароля». Убедимся, что все настроено правильно, нажав на кнопку «Проверить подключение».

Если мы все сделали правильно, в списке подключений Server Explorer появится новое, для которого будет доступен список объектов базы данных:

sampleWinforms_serverMan.gif

Создание каркаса приложения

Создайте новую форму JobForm. Добавьте на форму ComboBox и перейдите в редактор ComboBox Tasks:

smplEmployersCombobox1.gif

Далее необходимо в свойстве Data Source выбрать действие «Add Project Data Source». Откроется мастер создания источников данных:

smplCreateDataSourceWizz1.gif

Выбираем тип источника Database и идем далее. В списке подключений будет уже созданное ранее в Server Explorer подключение:

smplCreateDataSourceWizz2.gif

Делаем все, как показано на рисунке и переходим на следующий шаг:

smplCreateDataSourceWizz3.gif

Мастер предлагает нам сохранить параметры источника данных в файле конфигурации приложения. По умолчанию строка подключения будет сохранена в области «Application Settings» и будет не доступна для редактирования внутри приложения. Это можно изменить, установив для настройки свойство Scope = User. А пока разрешим создание секции в конфигурационном файле и двигаемся далее:

smplCreateDataSourceWizz4.gif

На завершающем шаге нам предлагают создать DataSet. Выберем для него все доступные таблицы базы данных и жмем кнопку «Finish».

Теперь в качестве источника данных для нашего ComboBox выбираем таблицу EMPLOYEE. Свойству DisplayMember установим значение FULL_NAME:

smplEmployersCombobox2.gif

После завершения операции на форму будут добавлены три новых компонента. Это DataSet, TableAdapter и BindingSource. DataSet нам уже знаком, а вот два других объекта появились только в Net 2.0 и будут рассмотрены далее.

Класс TableAdapter

Он является ключевым звеном в цепочке связи данных с пользовательскими элементами управления. Если провести аналогию с терминами М. Фаулера [1], то TableAdapter является шлюзом таблицы данных для DataTable. Он инкапсулирует в себе логику обновления загрузки и поиска данных и относится к Data Access Layer. Что же касается DataSet и DataTable, то их можно отнести к уровню бизнес-логики (Business Layer)

Visual Studio .Net 2005 сама позаботилась о генерации кода этого класса. Давайте посмотрим, что же она нам предлагает. Итак:

  • методы Fill() и GetData() – единственное отличие в том, что Fill принимает существующую DataTable в качестве аргумента, а GetData() создает новую, заполняет её данными и возвращает клиенту.
  • Свойство ClearBeforeFill, которое используется вышеназванными методами для определения, стоит ли очищать таблицу перед её заполнением.
  • Стандартный набор CRUD операций: insert, update, delete, среди которых присуствуют перегруженные методы с типизированными аргументами, соответствующими таблице базы данных
  • Общее свойство Connection

Так же у нас есть возможность создать дополнительные запросы к базе данных. Для этого нам понадобится инструмент Search Criteria Builder. Для его запуска необходимо у нашего адаптера выбрать пункт меню «Add Query»:

tableAdapter_AddQuery.gif

Вводим название запроса (а фактически название нового метода в вашем TableAdapte-е), а так же его текст, либо вручную указав условие выборки, либо используя инструмент Query Builder:

tableAdapter_AddQuerySteep2.gif



ПРИМЕЧАНИЕ.   При записи условия выборки используйте позиционные параметры (символ «?»). Код метода будет сгенерирован автоматически, так что особого неудобства это не доставит.

После всех операций будет сгенерирован соответствующий метод. Так же дизайнер VS .Net 2005 добавит компонент ToolStrip к вашей форме с кнопкой запуска этого метода и полем для задания фильтра. Мне кажется это излишним, но, может быть, кому-нибудь понравится.

СОВЕТ.  Visual Studio .Net 2005 разделяет код, используемый дизайнером и пользовательский код за счет partial классов. В нормальном приложении нам наверняка понадобиться расширить логику TableAdapter. Сделать это можно, описав partial class, соответствующий классу конкретного TableAdapter-a, сгенерированного дизайнером.
Передача изменений в базу данных через TableAdapter

Отдельно необходимо остановиться на методах передачи изменений обратно в базу данных. VS .Net 2005 умеет генерировать код запросов для методов insert, update, delete. В некоторых случаях этого может оказаться достаточно, но, как показывает опыт, полученные SQL-выражения пытаются претендовать на универсальность и поэтому не оптимальны, а порой не работоспособны.

Приведу пример: В поставке с Firebird идет база данных employee.fdb. В ней есть таблица SALES. Прежде всего, обращаю внимание на поле AGED, которое доступно только для чтения, т.к. вычисляется с помощью выражения

COMPUTED BY (ship_date - order_date)

Если указать для Select Command текст:

 SELECT * FROM SALES 

то колонка AGED будет добавлена во все команды обновления. При попытке передать изменения в базу, будет сгенерировано исключение. Необходимо вручную отредактировать текст запросов для insert, update, delete команд и убрать из обновления данную колонку.

Отредактировать SQL выражения можно, вызвав команду «Edit Queries in DataSet designer»:

tableAdapter_EditQueries1.gif

Откроется дизайнер DataSet, в котором необходимо выбрать нужный TableAdapter (в данном случае это SALESTTableAdapter):

tableAdapter_SALES_TABLE.gif

В списке свойств появятся необходимые нам объекты OleDbCommand:

tableAdapter_EditQueries2.gif

Читатель может подумать, что данный случай - исключение, но это не так. Если вы выберете такой способ создания слоя доступа к данным (Data Access Layer), то будьте готовы постоянно вмешиваться в автоматический процесс генерации SQL запросов.

BindingSource

С выходом Net 2.0 технология Data Binding получила свое дальнейшее развитие. Появился новый класс BindingSource. Он является прокси-объектом между поставщиками данных и элементами управления, отображающими эти данные. Теперь элемент управления привязывается не к объектам, поставляющим данные (DataTable, DataSet, DataView), а к объекту BindingSource. Это позволяет использовать привязку ещё незагруженных данных, а также синхронизировать данные в случае использования общего BindingSource для нескольких элементов управления.

Продолжая построение нашего приложения, приведу, на мой взгляд, яркий пример, который демонстрирует все преимущества объекта BindingSource.

Добавим на форму новый элемент управления DataGridView. Давайте попробуем отобразить в нем список проектов, у которых текущий служащий, выбранный в ComboBox-e, был руководителем. Известно, что таблицы PROJECT и EMPLOYEE связаны между собой через поле TEAM_LEADER по внешнему ключу INTEG_36. Воспользуемся уже знакомым механизмом связи элемента управления и источника данных:

smplProjectGridView1.gif

Необходимо найти в списке возможных источников данных уже использованный мной ранее BindingSource для таблицы служащих EMPLOYEE и запросить дизайнер создать новый BindingSource для связи между проектами и служащими по внешнему ключу INTEG_36:

Добавим элемент TextBox для отображения описания проекта, которое хранится в BLOB поле PROJECT_DESCR таблицы PROJECT. Для того, чтобы связать его с текущим проектом, в списке DataGridView необходимо установить Binding для свойства Text:

smplProjectTextBox1.gif

Добавление логики управления данными

Мы разобрались как отображать, связывать и редактировать данные. Теперь давайте завершим наш пример и научим приложение записывать сделанные нами изменения обратно в базу данных.

У нас единственным редактируемым полем является описание текущего проекта. Для записи изменений, сделанных в нем, мы воспользуемся методом TableAdapter.Update() для таблицы PROJECT. Добавим элемент Button на нашу форму и в обработчике cсобытия Click напишем следующий код:

private void btnSaveChanges_Click(object sender, EventArgs e)
{
        try 
        {
            this.pROJECTTableAdapter.Update(this.jobDataSet.PROJECT);
 		 MessageBox.Show("Save was successful");    
        }
        catch  (Exception exception)
        {
            MessageBox.Show(exception.Message);    
        }
}

Так же неплохо было бы иметь возможность откатить сделанные изменения. Добавим ещё одну кнопку и в обработчике события Click поместим код, который будет отменять все изменения в DataSet, произведенные с момента последнего сохранения:

  private void btnUndoChanges_Click(object sender, EventArgs e)
  {
         this.jobDataSet.RejectChanges();
         //требуется для обновления содержимого TextBox
         this.iNTEG36BindingSource.CurrencyManager.Refresh();   
  }

В процессе написания кода передачи изменений в БД, я столкнулся со следующей проблемой: при редактировании связанных данных через TextBox изменения не передавались в DataSet и метод DataSet.HasChanges() всегда возвращал false. Для решения этой проблемы необходимо в обработчик события TextBox.Validate добавить следующий код:

private void textBox1_Validated(object sender, EventArgs e)
{
        this.iNTEG36BindingSource.EndEdit();  
}

Завершенное приложение JobManager доступено в архиве с примерами к статье.

Схемы метаданных БД.

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

По этой ссылке расположен список схем, которые поддерживает IBProvider

Запросить определенную схему можно по её названию. Для этого у объекта OleDbConnection есть метод GetSchema(). В Net 2 появился метод GetOleDbSchema(), который в качестве аргумента принимает одно из значений OleDbSchemaGuid. Оба этих метода ведут себя одинаково и возвращают абсолютно идентичные экземпляры DataTable с набором информации по схеме.

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

Restriction columns: TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME. Если мы хотим получить описание всех колонок для таблицы EMPLOYEE, мы должны использовать схему COLUMNS следующим образом:

DataTable schema_table = 
connection.GetSchema("COLUMNS", new string[] { null, null, "EMPLOYEE" });

Аналогично для метода GetOleDbSchema():

DataTable schema_table =
connnection.GetOleDbSchemaTable(OleDbSchemaGuid.Columns, new object[] { null, null, "EMPLOYEE" });

DDL запросы. CREATE/ALTER/DROP

Данный вид запросов позволяет управлять метаданными БД. Вы можете создавать, удалять и модифицировать колонки, таблицы и целые базы данных через SQL выражения, в тексте которых содержатся DDL-инструкции. Если применять их совместно со схемами метаданных, то можно без особых усилий копировать структуры существующих баз данных и создавать новые.

Все DDL запросы, за исключением CREATE DATABASE и DROP DATABASE, могут выполняться как в режиме автоматического подтверждения, так и в контексте транзакции. По умолчанию фиксирование изменений произведенных DDL запросами отключено. Это сделано из соображений безопасности. Для того, чтобы включить подтверждение DDL запросов, необходимо установить свойство auto_commit_ddl. Его описание есть в разделе «Методы подключения к базе данных» этой статьи.

Приведу пример использования DROP DATABASE для удаления базы данных:

private void DropDatabase()
{ 
    if (File.Exists(databasePath))
    {
 	    OleDbConnectionStringBuilder builder = 
 	       CreateConnectionStringBuilderForSample();
      
        //отключаем использование пула для этого подключения
        builder.OleDbServices = OleDbServicesValues.EnableAll & 
                                ~OleDbServicesValues.ResourcePooling;   

        OleDbConnection con = new OleDbConnection(builder.ToString());
        con.Open();

        new OleDbCommand("drop database",con).ExecuteNonQuery();           
        con.Close();
    }
}

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

Теперь DDL для создания новой базы данных:

private OleDbConnection CreateDatabase()
{
    //подключение к существующей бд employee.gdb
    OleDbConnection con = ConnectionProvider.CreateConnection();
    con.Open();

    //создание новой базы данных
    new OleDbCommand(
               "create database '" + server_name + ":" + databasePath + "'\n" +
                       "USER     '" + user_name + "'    \n" +
                       "PASSWORD '" + password + "' \n", con).ExecuteNonQuery();
                        
    con.Close();

    return new OleDbConnection(
 	      CreateConnectionStringBuilderForSample().ToString());         
}

И, наконец, законченный пример, который сначала удаляет базу данных, потом создает на её месте новую и определяет в ней две таблицы, связанные внешним ключом:

public void CreateNewDBSample()
{    
    DropDatabase();

    OleDbConnection con = CreateDatabase();
    con.Open();            
    OleDbTransaction trans = con.BeginTransaction();

    //создаем таблицу SAMPLE_TABLE с двумя колонками
    ExecuteDDL(
        "CREATE TABLE SAMPLE_TABLE(                     " + //int column                
        " ID             INTEGER      NOT NULL,         " + //varchar column
        " NAME           VARCHAR(64),                   " + //primary key
        "CONSTRAINT PK_SAMPLE_TABLE PRIMARY KEY(ID)    )", trans);

    //создаем SAMPLE_TABLE_2 связанную через FOREIGN KEY 
    ExecuteDDL(
        "CREATE TABLE SAMPLE_TABLE_2 (                  " +                
        " ID             INTEGER      NOT NULL,         " + //int columns
        " PARENT         INTEGER      NOT NULL,         " + //int column
        "CONSTRAINT PK_SAMPLE_TABLE_2 PRIMARY KEY(ID),   " + //primary key
        "CONSTRAINT FK_SAMPLE_TABLE_PARENT              " +  //foreign key
        "FOREIGN KEY(PARENT) REFERENCES SAMPLE_TABLE(ID))", trans);

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

Управляющие последовательности ODBC

Управляющие последовательности позволяют преобразовывать текст запроса в процессе выполнения. Последовательность включается в текст запроса в фигурных скобках. Например {fn CURDATE} – выражение будет преобразовано в значение серверного времени.

В ODBC определены управляющие последовательности для следующих характеристик:

  • Работа со временем и датами
  • Функции преобразования типов
  • Предикат LIKE
  • OUTER JOIN
  • Вызовы хранимых процедур

Данное расширение активно используется такими инструментами, как MS SQL Server, Crystal Reports, различные OLAP средства и их поддержка со стороны Ole Db провайдера обеспечивает возможность их совместного использования.

Для того, чтобы включить поддержку ODBC расширений в IBProvider, необходимо установить свойство инициализации support_odbc_call = true. По умолчанию поддержка отключена.

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

  • Функции для работы с датами и временем: CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP, CURDATE, CURTIME, DAYNAME, DAYOFMONTH, DAYOFWEEK, DAYOFYEAR, EXTRACT, HOUR, MINUTE, MONTH, MONTHNAME, NOW, QUARTER, SECOND, WEEK, YEAR.
  • Конвертирование данных: CONVERT
  • Системные функции: USER
  • Строковые функции: UCASE

Следующий пример демонстрирует применение управляющих последовательностей в тексте SQL запросов:

public void ODBCQueriesTest()
{
   OleDbConnectionStringBuilder builder = 
ConnectionProvider.GetConnectionStringBuilderFromUDL();
   builder.Provider = "LCPI.IBProvider.2";
   builder.Add("support_odbc_query","true");
 
   OleDbConnection con = new OleDbConnection(builder.ToString());                 
   con.Open();
   OleDbTransaction trans = con.BeginTransaction();

   //select current day name
   OleDbCommand cmd = new OleDbCommand(
       "select " +
       "{fn dayname({fn now()})} as DAY_NAME," +
       "{fn dayofweek({fn now()})} as DAY_OF_WEEK," +
       "{fn dayofmonth({fn now()})} as DAY_OF_MONTH," +
       "{fn dayofyear({fn now()})} as DAY_OF_YEAR " +
       "from RDB$DATABASE", con, trans);

   using (OleDbDataReader rdr = cmd.ExecuteReader())
       if (rdr.Read())
           for (int i = 0; i < rdr.FieldCount; i++)
                  Console.WriteLine(rdr.GetName(i) + ": " + rdr[i].ToString()); 
            
   trans.Commit();  
   con.Close(); 
 }

На момент написания статьи ODBC запросы поддерживались в 1-й и 2-й версии IBProvider и ещё не были реализованы в третьей. Так что для использования этой возможности необходимо указывать в строке подключения Provider = "LCPI.IBProvider.2"

За более подробной информацией по использованию управляющих последовательностей ODBC советую вам обратиться к документу «ODBC Programmer’s Reference» и изучить раздел «Escape Characters in ODBC».

Заключение

В своем обзоре я рассмотрел наиболее часто используемые возможности библиотеки ADO .Net на примере OLE DB провайдера.

Основное преимущество OLE DB провайдеров перед управляемыми (.Net Data Providers) – это возможность их использования не только в среде .Net Framework, а практически в любых средах, поддерживающих COM.

Использование IBProvider в качестве поставщика данных Firebird позволяет:

  • Обмениваться данными с приложениями Microsoft Office (включая Access и Outlook)
  • Использовать VBA (Visual Basic for Applications).
  • Выгружать данные в 1С и обратно.
  • Использовать Firebird в качестве связанного сервера MS SQL.
  • Писать расширенные сценарии автоматизации при помощи WSH (Windows Script Host), VBScript, Java Script
  • Писать WEB-приложения, WEB-сервисы c базами данных не только на ASP.Net, но и на ASP
  • Производить анализ данных при помощи различных OLAP средств за счет поддержки ODBC управляющих последовательностей.
  • Использовать провайдер в составе распределенных транзакций
  • И ещё много чего.

IBProvider поддерживает все существующие версии Interbase/Yaffil/Firebird. Имеет встроенный менеджер управления памятью и SWAP для пользовательских данных. Поддерживает многопоточность, а так же серверные и клиентские курсоры. Осуществляет многоязыковую поддержку.

Надеюсь, данное руководство позволит вам расширить круг применяемых возможностей ADO .Net не только для работы с Firebird, но и с другими базами данных.

Полезные ссылки

Список литературы

Литература

1.обратноМ.Фаулер. Архитектура корпоративных программных приложений. Изд. Москва – Спб – Киев. 2004 г.
2.обратноЭ. Гамма, Р. Хелм, Р. Джонсон, Дж. Влиссидес. Приемы объектно-ориентированного проектирования. Паттерны проектирования. Изд. Питер. 2006 г.
3.А. Ковязин, С.Востриков. Мир InterBase. Архитектура, администрирование и разработка приложений баз данных в InterBase/Firebird/Yaffil (+ CD-ROM). Изд. КУДИЦ-Образ, Питер. 2005 г.
4.Б.Бошемин. Основы ADO .Net. Изд. Вильямс. 2003 г.


Примеры к статье


НазадСодержание
VPS в 21 локации

От 104 рублей в месяц

Безлимитный трафик. Защита от ДДоС.

🔥 VPS до 5.7 ГГц под любые задачи с AntiDDoS в 7 локациях

💸 Гифткод CITFORUM (250р на баланс) и попробуйте уже сейчас!

🛒 Скидка 15% на первый платеж (в течение 24ч)

Скидка до 20% на услуги дата-центра. Аренда серверной стойки. Colocation от 1U!

Миграция в облако #SotelCloud. Виртуальный сервер в облаке. Выбрать конфигурацию на сайте!

Виртуальная АТС для вашего бизнеса. Приветственные бонусы для новых клиентов!

Виртуальные VPS серверы в РФ и ЕС

Dedicated серверы в РФ и ЕС

По промокоду CITFORUM скидка 30% на заказ VPS\VDS

Новости мира IT:

Архив новостей

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

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