Kniga-Online.club
» » » » А Ковязин - Мир InterBase. Архитектура, администрирование и разработка приложений баз данных в InterBase/FireBird/Yaffil

А Ковязин - Мир InterBase. Архитектура, администрирование и разработка приложений баз данных в InterBase/FireBird/Yaffil

Читать бесплатно А Ковязин - Мир InterBase. Архитектура, администрирование и разработка приложений баз данных в InterBase/FireBird/Yaffil. Жанр: Программирование издательство неизвестно, год 2004. Так же читаем полные версии (весь текст) онлайн без регистрации и SMS на сайте kniga-online.club или прочесть краткое содержание, предисловие (аннотацию), описание и ознакомиться с отзывами (комментариями) о произведении.
Перейти на страницу:

rs Close

'альтернативой auto_commit=true является установка

'(после успешного подключения к база данных)

'свойства сессии Session AutoCommit=true.

'В ADODB это одно и то же,

'поскольку на одно подключение - одна сессия

'через это же свойство можно "выключить" глобальное

'разрешение на автоматический

'запуск транзакции, что дальше и демонстрируется

cn Properties("Session AutoCommit") = False

cmd.CommandText = "select * from rdb$database"

Set rs = cmd Execute

'выдаст олибку "Automatic transaction is disabled"

При программировании на C++ принципы взаимодействия с сессией точно такие же. Но в C++ сессия будет отдельным объектом.

В нижеследующем примере на C++ демонстрируется трюк, который часто используется для моделирования принудительного завершения транзакций. Дело в том, что InterBase реализует многоверсионную архитектуру данных (подробнее о многоверсионности данных см. главу "Транзакции Параметры транзакций" (ч 1)) Одной из особенностей такой архитектуры является то, что любые транзакции желательно завершать подтверждением (commit), а не откатом (lollback).

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

try

{

t_db_data_source cn;

_THROto_OLEDB_FAILED(en,attacn("provider=LCPI.IBProvxCter.1,"

"data source=localhost:d:\database\employee.gdb;"

"user id=gamer;"

"password=vermut"));

t_db_session session;

// метод create перегружен для разных типов аргумента, поэтому

// можно передавать

// как C++ объект (t_db_data_source), так и IUnknown источника

// данных

_THROW_OLEDB_FAILED(session,create(en)) ,

// запуск транзакции

_THROW_OLEDB_FAILED(session,start_transaction() ) ;

// создаем объект для принудительного завершения транзакции

t_auto_mem_fun_l<HRESULT,bool,t_db_session>

_auto_commit_(session, /*commit_retaining=*/false, &t_db_session::commit);

//... теперь, что бы ни произошло, транзакция

// будет "закоммичена"

throw runtime_error("This is my test error");

}

catcn(const exception& exc)

{

cout<< "error:"<<exc.what()<<endl;

}

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

Распределенные транзакции

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

На практике распределенные транзакции обычно используются в СОМ+ (MTS) и Microsoft Distributed Query. В первом случае существует следующая особенность. Когда компоненты просят у своего окружения предоставить им подключение к базе данных, то на каждый такой запрос создается отдельная пара источник данных - сессия. Связано это с описанным выше принципом работы пула подключений. Если компонентов, обрабатывающих пользовательский запрос, очень много и они работают с одной и той же базой данных с идентичными параметрами подключения, то имеет смысл один раз получить подключение и потом предоставлять его компонентам. Иначе в распределенной транзакции будет использовано множество сессий, каждая из которых соответствует процессу или потоку на сервере базы данных, что может привести к резкому снижению производительности сервера СУБД.

Использование нескольких сессий в ADODB

Несмотря на то что модель объектов ADODB не предоставляет прямой возможности одновременного использования нескольких сессий с одним источником данных, это ограничение можно обойти. Решение основывается на применение внутреннего интерфейса ADOConnectionConstruction компоненты ADODB.Connection.

void clone_adodb_connection(IDispatch* pCurrentConnection,

IDispatchPtr& spNewConnection)//throw

{

//объявляем типы смарт-указателей для интерфейсов

//конструирования ADODB-подключения

DECLARE_IPTR_TYPE(ADOConnectionConstruction);

DECLARE_IPTR_TYPE(ADOConnectionConstructionl5);

//1 получаем источник данных, привязанный к pCurrentConnection

ADOConnectionConstructionPtr

spConstruct(pCurrentConnection);

ADOConnectionConstruetionl5Ptr

spConstructlS(pCurrentConnection);

if(!spConstruct && !spConstruct15)

t_ole_error::throw_error("Объект - не ADODB.Connection",

E_INVALIDARG);

IUnknownPtr spDataSource;

//берем указатель на OLE DB-источник данных

if((bool)spConstruct15)

spConstruct15->get_DSO(&spDataSource.ref_ptr());

if(!spDataSource && (bool)spConstruct)

spConstruct->get_DSO(&spDataSource.ref_ptr());

if(!spDataSource)

t_ole_error::throw_error(

"ADODB.Connection не инициализирован",E_FAIL);

//2 создаем новую сессию для spDataSource ------------------

IUnknownPtr spNewSession;

IDBCreateSessionPtr spDBCreateSession(spDataSource);

assert((bool) spDBCreateSession);

if(FAILED(spDBCreateSession->CreateSession

(NULL,IID_IUnknown,kspNewSession.ref_ptr())))

{

t_ole_error::throw_error(

"Ошибка создания новой сессии",E_FAIL);

}

assert((bool)spNewSession);

//3 создаем новый экземпляр ADODB.Connection ----------------

IUnknownPtr spUnkNewConnection;

HRESULT hr=SafeCreateInstance("ADODB.Connection",

NULL,CLSCTX_INPROC,IID_IUnknown,

(void**)&spUnkNewConnection.ref_ptr());

if(FAILED(hr))

t_ole_error::throw_error(

"Ошибка создания "ADODB.Connection"",hr);

spConstruet = spUnkNewConnection;

spConstruct15=spUnkNewConnection;

if(!spConstructlS && !spConstruct)

throw t_ole_error(

"Ошибка подключения к "ADODB.Connection"",E_FAIL);

spDataSource->AddRef(); //ADO не вызывает для них AddRef spNewSession->AddRef();

//при конструировании ADODB.Connection

//пытается установить свои свойства,

//в результате чего, если IBProvider уже подключен

//к базе данных, может произойти ошибка

//тем не менее подключение уже сконструировано

//и вполне работоспособно.

if((bool)spConstructlS) //IID_Connect-on15

{

spConstruct15->WrapDSOandSession(spDataSource,spNewSession);

hr = spUnkNewConnection ->

Querylnterface(IID_ConnectionlS,spNewConnection);

}

else //IID_Connection

{

spConstruct->WrapDSOandSession(spDataSource,spNewSession);

hr = spUnkNewConnection ->

Querylnterface(IID_Connection,spNewConnection);

}

if (FAILED(hr))

t_ole_error::throw_error(

"Ошибка получения IDispatch из ADODB.Connection",hr);

assert((bool)spNewConnection);

//всё — spNewConnection подключен к тому же

//источнику данных, но обладает

//собственной сессией.

}//cione_adodb_connection

Чтение метаданных

Помимо управления транзакциями, сессия предоставляет еще одну полезную возможность - получение метаданных для базы данных (о метаданных см. главу "Структура базы данных InterBase" (ч. 4)). Поскольку в некоторых системах, например в Microsoft Distributed Query, операция получения метаданных выполняется очень часто, то IBProvider хранит информацию о них в оперативной памяти (т. е. кеширует). Кэширование метаданных можно настраивать для обеспечения оптимального быстродействия. Определить режим кеширования можно через свойство инициализации источника данных "schema_cache" и свойство сессии - "Session Schema Cache". Этим свойствам можно присваивать следующие значения:

* Кэширование запрещено. Данные будут всегда перечитываться.

* Глобальное кеширование на уровне Data Source. Это режим по умолчанию.

* Кеширование на уровне Session.

Если при запросе метаданных сессия содержит явно запущенную транзакцию, то провайдер не будет использовать дополнительную внутреннюю транзакцию для получения данных, а воспользуется уже существующей. Если явно запущенной транзакции нет, то IBProvider автоматически запустит внутреннюю транзакцию с уровнем изоляции, указанной в свойстве сессии "Autocommit Isolation Levels". Для запрещения автоматического запуска провайдером внутренних транзакций для извлечения метаданные необходимо определить в строке инициализации источника данных "inner_trans=false" или установить свойство сессии "Session InnerTrans=false".

Получение и вывод списка таблиц базы данных:

ADODB

Dim cn As New ADODB.Connection

Call cn.Open("file name=d:databaseemployee.ibp")

Dim rs As ADODB.Recordset

Set rs = cn.OpenSchema(adSchemaTables)

Cells.Clear

Dim col As Long, row As Long

row = 1

'печать названия колоник

For col = 0 To rs.Fields.Count - 1

Cells(row, col + 1) = rs(col).Name

Next col

'печать содержимого

While Not rs.EOF

row = row + 1

For col = 0 To rs.Fields.Count - 1

Cellsfrow, col + 1) = rs(col).Value

Next col

rs.MoveNext

Wend

Здесь следует обратить внимание на одну особенность. Спецификация OLE DB для некоторых полей таблиц метаданных определяет типы, несовместимые с VARIANT, например UI8. Поэтому при попытке получения значения из этих полей через ADODB может возникнуть ошибка;

C++

try

{

t_db_data_source сn;

_THROW_OLEDB_FAILED(cn,attach("file

name=d:\database\employee.ibp"));

t_db_session session;

_THROW_OLEDB_FAILED(session,create(сn));

//библиотека напрямую не поддерживает

//работу с интерфейсом получения

//наборов информационной схемы,

//поэтому напишем необходимый код "в лоб".

IDBSchemaRowsetPtr spSR(session.session_obj());

if(!spSR)

t_ole_error::throw_error(

"query interface [IDBSchemaRowset]",spSR.m_hr);

Перейти на страницу:

А Ковязин читать все книги автора по порядку

А Ковязин - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки kniga-online.club.


Мир InterBase. Архитектура, администрирование и разработка приложений баз данных в InterBase/FireBird/Yaffil отзывы

Отзывы читателей о книге Мир InterBase. Архитектура, администрирование и разработка приложений баз данных в InterBase/FireBird/Yaffil, автор: А Ковязин. Читайте комментарии и мнения людей о произведении.


Уважаемые читатели и просто посетители нашей библиотеки! Просим Вас придерживаться определенных правил при комментировании литературных произведений.

  • 1. Просьба отказаться от дискриминационных высказываний. Мы защищаем право наших читателей свободно выражать свою точку зрения. Вместе с тем мы не терпим агрессии. На сайте запрещено оставлять комментарий, который содержит унизительные высказывания или призывы к насилию по отношению к отдельным лицам или группам людей на основании их расы, этнического происхождения, вероисповедания, недееспособности, пола, возраста, статуса ветерана, касты или сексуальной ориентации.
  • 2. Просьба отказаться от оскорблений, угроз и запугиваний.
  • 3. Просьба отказаться от нецензурной лексики.
  • 4. Просьба вести себя максимально корректно как по отношению к авторам, так и по отношению к другим читателям и их комментариям.

Надеемся на Ваше понимание и благоразумие. С уважением, администратор kniga-online.


Прокомментировать
Подтвердите что вы не робот:*
Подтвердите что вы не робот:*