事務物件和命令物件
title: 事務物件和命令物件
tags: [OLEDB, 資料庫程式設計, VC++, 資料庫]
date: 2018-01-21 09:22:10
categories: windows 資料庫程式設計
keywords: OLEDB, 資料庫程式設計, VC++, 資料庫
上次說到資料來源物件,這次接著說事務物件和命令物件。
事務是一種對資料來源的一系列更新進行分組或批處理以便當所有更新都成功時同時提交這些更新,或者如果任何一個更新失敗則不提交任何更新並且回滾整個事務的方法.
命令物件一般是用來執行sql語句並生成結果集的物件
會話物件
在OLEDB中通過以下3中方式支援事務:
- ITransactionLocal::StartTransaction
- ITransaction::commit
- ITransaction::Abort
OLEDB中定義事務和回話物件的介面如下:
CoType TSession {
[mandatory] interface IGetDataSource;
[mandatory] interface IOpenRowset;
[mandatory] interface ISessionProperties;
[optional] interface IAlterIndex;
[optional] interface IAlterTable;
[optional] interface IBindResource;
[optional] interface ICreateRow;
[optional] interface IDBCreateCommand;
[optional] interface IDBSchemaRowset;
[optional] interface IIndexDefinition;
[optional] interface ISupportErrorInfo;
[optional] interface ITableCreation;
[optional] interface ITableDefinition;
[optional] interface ITableDefinitionWithConstraints;
[optional] interface ITransaction;
[optional] interface ITransactionJoin;
[optional] interface ITransactionLocal;
[optional] interface ITransactionObject;
}
在建立了資料庫連線之後使用QueryInterface 查詢出IDBCreateSeesion物件,然後呼叫IDBCreateSession的CreateSession方法建立一個回話物件。
需要注意的是,一個資料來源連線可以建立多個回話物件,這裡只能通過這種方式建立回話物件,而不能直接通過CoCreateInstance 來建立。一般來說應用中至少建立一個會話物件
Command物件
Command物件的定義如下:
CoType TCommand {
[mandatory] interface IAccessor;
[mandatory] interface IColumnsInfo;
[mandatory] interface ICommand;
[mandatory] interface ICommandProperties;
[mandatory] interface ICommandText;
[mandatory] interface IConvertType;
[optional] interface IColumnsRowset;
[optional] interface ICommandPersist;
[optional] interface ICommandPrepare;
[optional] interface ICommandWithParameters;
[optional] interface ISupportErrorInfo;
[optional] interface ICommandStream;
}
一般建立Command物件是通過Session物件Query出來一個IDBCreateCommand介面讓後呼叫CreateCommand方法建立。
與會話物件相似,一個會話物件可以建立多個命令物件,但是從上面會話物件的定義可以看出IDBCreateCommand介面是一個可選介面,並不是所有的資料庫都支援,因此在建立命令物件的時候一定要注意判斷是否支援。對於不支援的可以採用其他辦法(一般採用直接開啟資料庫表的方式)。
下面是一個演示例子:
#define CHECK_OLEDB_INTERFACE(I, iid)\
hRes = (I)->QueryInterface(IID_##iid, (void**)&(p##iid));\
if(FAILED(hRes))\
{\
OLEDB_PRINTF(_T("不支援介面:%s\n"), _T(#iid));\
}\
else\
{\
OLEDB_PRINTF(_T("支援介面:%s\n"), _T(#iid));\
}
BOOL CreateDBSession(IOpenRowset* &pIOpenRowset)
{
DECLARE_BUFFER();
DECLARE_OLEDB_INTERFACE(IDBPromptInitialize);
DECLARE_OLEDB_INTERFACE(IDBInitialize);
DECLARE_OLEDB_INTERFACE(IDBCreateSession);
BOOL bRet = FALSE;
HWND hDesktop = GetDesktopWindow();
HRESULT hRes = CoCreateInstance(CLSID_DataLinks, NULL, CLSCTX_INPROC_SERVER, IID_IDBPromptInitialize, (void**)&pIDBPromptInitialize);
OLEDB_SUCCESS(hRes, _T("建立介面IDBPromptInitialize失敗,錯誤碼:%08x\n"), hRes);
hRes = pIDBPromptInitialize->PromptDataSource(NULL, hDesktop, DBPROMPTOPTIONS_WIZARDSHEET, 0, NULL, NULL, IID_IDBInitialize, (IUnknown**)&pIDBInitialize);
OLEDB_SUCCESS(hRes, _T("彈出介面資料來源配置對話方塊失敗,錯誤碼:%08x\n"), hRes);
hRes = pIDBInitialize->Initialize();
OLEDB_SUCCESS(hRes, _T("連結資料庫失敗,錯誤碼:%08x\n"), hRes);
hRes = pIDBInitialize->QueryInterface(IID_IDBCreateSession, (void**)&pIDBCreateSession);
OLEDB_SUCCESS(hRes, _T("建立介面IDBCreateSession失敗,錯誤碼:%08x\n"), hRes);
hRes = pIDBCreateSession->CreateSession(NULL, IID_IOpenRowset, (IUnknown**)&pIOpenRowset);
OLEDB_SUCCESS(hRes, _T("建立介面IOpenRowset失敗,錯誤碼:%08x\n"), hRes);
bRet = TRUE;
__CLEAR_UP:
OLEDB_SAFE_RELEASE(pIDBPromptInitialize);
OLEDB_SAFE_RELEASE(pIDBInitialize);
OLEDB_SAFE_RELEASE(pIDBCreateSession);
return bRet;
}
int _tmain(int argc, TCHAR *argv[])
{
DECLARE_BUFFER();
DECLARE_OLEDB_INTERFACE(IOpenRowset);
DECLARE_OLEDB_INTERFACE(IDBInitialize);
DECLARE_OLEDB_INTERFACE(IDBCreateCommand);
DECLARE_OLEDB_INTERFACE(IAccessor);
DECLARE_OLEDB_INTERFACE(IColumnsInfo);
DECLARE_OLEDB_INTERFACE(ICommand);
DECLARE_OLEDB_INTERFACE(ICommandProperties);
DECLARE_OLEDB_INTERFACE(ICommandText);
DECLARE_OLEDB_INTERFACE(IConvertType);
DECLARE_OLEDB_INTERFACE(IColumnsRowset);
DECLARE_OLEDB_INTERFACE(ICommandPersist);
DECLARE_OLEDB_INTERFACE(ICommandPrepare);
DECLARE_OLEDB_INTERFACE(ICommandWithParameters);
DECLARE_OLEDB_INTERFACE(ISupportErrorInfo);
DECLARE_OLEDB_INTERFACE(ICommandStream);
CoInitialize(NULL);
if (!CreateDBSession(pIOpenRowset))
{
OLEDB_PRINTF(_T("呼叫函式CreateDBSession失敗,程式即將推出\n"));
return 0;
}
HRESULT hRes = pIOpenRowset->QueryInterface(IID_IDBCreateCommand, (void**)&pIDBCreateCommand);
OLEDB_SUCCESS(hRes, _T("建立介面IDBCreateCommand失敗,錯誤碼:%08x\n"), hRes);
hRes = pIDBCreateCommand->CreateCommand(NULL, IID_IAccessor, (IUnknown**)&pIAccessor);
OLEDB_SUCCESS(hRes, _T("建立介面IAccessor失敗,錯誤碼:%08x\n"), hRes);
CHECK_OLEDB_INTERFACE(pIAccessor, IColumnsInfo);
CHECK_OLEDB_INTERFACE(pIAccessor, ICommand);
CHECK_OLEDB_INTERFACE(pIAccessor, ICommandProperties);
CHECK_OLEDB_INTERFACE(pIAccessor, ICommandText);
CHECK_OLEDB_INTERFACE(pIAccessor, IConvertType);
CHECK_OLEDB_INTERFACE(pIAccessor, IColumnsRowset);
CHECK_OLEDB_INTERFACE(pIAccessor, ICommandPersist);
CHECK_OLEDB_INTERFACE(pIAccessor, ICommandPrepare);
CHECK_OLEDB_INTERFACE(pIAccessor, ICommandWithParameters);
CHECK_OLEDB_INTERFACE(pIAccessor, ISupportErrorInfo);
CHECK_OLEDB_INTERFACE(pIAccessor, ICommandStream);
__CLEAR_UP:
OLEDB_SAFE_RELEASE(pIOpenRowset);
OLEDB_SAFE_RELEASE(pIDBInitialize);
OLEDB_SAFE_RELEASE(pIDBCreateCommand);
OLEDB_SAFE_RELEASE(pIAccessor);
OLEDB_SAFE_RELEASE(pIColumnsInfo);
OLEDB_SAFE_RELEASE(pICommand);
OLEDB_SAFE_RELEASE(pICommandProperties);
OLEDB_SAFE_RELEASE(pICommandText);
OLEDB_SAFE_RELEASE(pIConvertType);
OLEDB_SAFE_RELEASE(pIColumnsRowset);
OLEDB_SAFE_RELEASE(pICommandPersist);
OLEDB_SAFE_RELEASE(pICommandPrepare);
OLEDB_SAFE_RELEASE(pICommandWithParameters);
OLEDB_SAFE_RELEASE(pISupportErrorInfo);
OLEDB_SAFE_RELEASE(pICommandStream);
CoUninitialize();
return 0;
}
在上述的例子中,首先定義了一個巨集,用來判斷是否支援對應的介面。
同時定義了一個CreateDBSession方法來建立一個會話物件。在該函式中首先利用上一節的方法建立一個資料庫連線,然後在資料來源物件上呼叫QueryInterface來獲取介面IDBCreateSeesion,接著利用IDBCreateSeesion介面的CreateSeesion方法建立一個會話物件,由於IDBCreateCommand介面並不是所有的資料來源都支援,所以為了保證一定能建立會話物件,我們選擇會話物件必須支援的介面IOpenRowset。
在得到會話物件後,嘗試建立IDBCreateSession物件,如果它不支援,那麼程式直接退出。接著呼叫IDBCreateCommand介面來建立一個命令物件並嘗試query命令物件的其他介面,得出資料來源支援哪些介面。
這個例子非常簡單,只是為了演示如何建立會話物件和資料來源物件罷了。
本節例子程式碼
<hr />
相關文章
- hibernate的事務管理和session物件的詳解Session物件
- PHP MySQL (三)物件導向 事務PHPMySql物件
- 資料庫主要物件及事務資料庫物件
- 一些轉儲和清除記憶體物件和物理物件的命令記憶體物件
- PHP物件和介面抽象類注意事項PHP物件抽象
- session物件、cookie物件和appliaction物件Session物件CookieAPP
- DAOS 分散式非同步物件儲存|事務模型分散式非同步物件模型
- jQuery物件和DOM物件jQuery物件
- 一些轉儲和清除記憶體物件和物理物件的命令(轉)記憶體物件
- 服務物件物件
- Spring事務管理與AOP代理的原理,預設的單例物件和代理物件銷燬的時機Spring單例物件
- Django:F物件和Q物件Django物件
- JavaScript 本地物件、內建物件和宿主物件JavaScript物件
- Java 物件頭那點事Java物件
- JavaScript內部物件和Date物件JavaScript物件
- 區別 Jquery物件和Dom物件jQuery物件
- javascript物件和php物件和json區別JavaScript物件PHPJSON
- 內建物件、宿主物件和本地物件是什麼物件
- Django(26)HttpResponse物件和JsonResponse物件DjangoHTTP物件JSON
- 複習JAVA面相物件(類和物件)Java物件
- 物件和類物件
- 類和物件物件
- js關於物件那點事JS物件
- 物件導向 - Java那些事兒物件Java
- 關於v$session中的taddr列(事務物件地址)Session物件
- Python可變物件和不可變物件Python物件
- jquery物件和DOM物件的互相轉換jQuery物件
- JavaScript物件導向—物件的建立和操作JavaScript物件
- 物件儲存服務中物件業務的非標介面物件
- 【胡思亂想】命令模式中,命令物件如何解耦Invoker和Receiver模式物件解耦
- jQuery物件和DOM物件和字串之間的轉化jQuery物件字串
- 關於JavaScript物件,你所不知道的事(一)- 先談物件JavaScript物件
- 關於JavaScript原型物件那些事兒JavaScript原型物件
- SQLServer 物件建立注意事項之dboSQLServer物件
- Scala 類和物件物件
- Java 物件和類Java物件
- 類和物件(中)物件
- Java 類和物件Java物件