- 浏览: 4472112 次
最新评论
Using OLE DB Consumer Templates
Using OLE DB Consumer Templates
CComBSTR LoadUDL(const CComBSTR& udlPath)
{
CComPtr<IDataInitialize> spDataInitialize;
HRESULT hr = spDataInitialize.CoCreateInstance( __uuidof(MSDAINITIALIZE));
CComHeapPtr<OLECHAR> conString;
if (SUCCEEDED(hr))
{
hr=spDataInitialize->LoadStringFromStorage(udlPath, &conString);
if(hr!=S_OK)
{
cout<<"LoadStringFromStorage failed"<<endl;
return CComBSTR(L"");
}
return CComBSTR(conString);
}
cout<<"CoCreateInstance( __uuidof(MSDAINITIALIZE)) failed"<<endl;
return CComBSTR(L"");
}
CDataConnection con;
HRESULT hr=con.Open(conString);//conString can be generated by LoadUDL function
We can also connect to a database by using CDataSource::Open member function.What’s the difference between CDataConnection and CDataSource? CDataConnection is a useful class for creating clients because it encapsulates necessary objects (data source and session) and some of the work you need to do when connecting to a data source.
//Popup a data link property dialog to connect database
CDataSource source;
HRESULT hr=source.Open();
CComBSTR conStr;
source.GetInitializationString(&conStr,true);
//Popup a data link property dialog to connect database
CDataSource source;
HRESULT hr=source.Open();
CComBSTR conStr;
source.GetInitializationString(&conStr,true);
CComBSTR GetDatabaseProviderName(const CDataSource& ds)
{
CComVariant var;
HRESULT hr = ds.GetProperty( DBPROPSET_DATASOURCEINFO, DBPROP_PROVIDERNAME, &var );
if(hr==S_OK)
{
return var.bstrVal;
}
return CComBSTR(L"");
}
HRESULT GetTableNames(const CDataConnection& con,vector<CComBSTR>& names)
{
if(!names.empty())
{
names.clear();
}
CTables ts;
HRESULT hr=ts.Open(con.m_session,NULL,NULL,NULL,_T("TABLE"));
if( FAILED(hr) )
{
cout<<"Unable to open the TABLES schema to get the list of available tables"<<endl;;
return hr;
}
hr = ts.MoveFirst();
while( SUCCEEDED( hr ) && hr != DB_S_ENDOFROWSET )
{
names.push_back(ts.m_szName);
hr = ts.MoveNext();
}
if(names.empty())
{
return S_FALSE;
}
else
{
return S_OK;
}
}
void GetPrimaryKeys(CDataConnection& con,vector<CString>& pkeys)
{
CPrimaryKeys key;
HRESULT hr=key.Open(con.m_session,NULL,NULL,_T("pet"));
while(S_OK==key.MoveNext())
{
pkeys.push_back(key.m_szColumnName);
}
}
HRESULT OpenByDynamicAccessor(const CDataConnection& con,const CComBSTR& sql)
{
CCommand<CDynamicAccessor> rs;
CDBPropSet pset( DBPROPSET_ROWSET );
pset.AddProperty( DBPROP_ISequentialStream, true, DBPROPOPTIONS_OPTIONAL );
pset.AddProperty( DBPROP_IStream, true, DBPROPOPTIONS_OPTIONAL );
pset.AddProperty( DBPROP_CANFETCHBACKWARDS, true, DBPROPOPTIONS_OPTIONAL );
pset.AddProperty( DBPROP_CANSCROLLBACKWARDS, true, DBPROPOPTIONS_OPTIONAL );
return rs.Open(con.m_session, sql, &pset );
}
HRESULT OpenByDynamicAccessor(CDataConnection& con,const CComBSTR& sql)
{
CCommand<CDynamicAccessor> rs;
CDBPropSet pset( DBPROPSET_ROWSET );
pset.AddProperty( DBPROP_ISequentialStream, true, DBPROPOPTIONS_OPTIONAL );
pset.AddProperty( DBPROP_IStream, true, DBPROPOPTIONS_OPTIONAL );
pset.AddProperty( DBPROP_CANFETCHBACKWARDS, true, DBPROPOPTIONS_OPTIONAL );
pset.AddProperty( DBPROP_CANSCROLLBACKWARDS, true, DBPROPOPTIONS_OPTIONAL );
//If the table has blob column,you must call this method
rs.SetBlobHandling( DBBLOBHANDLING_SKIP );
return rs.Open(con.m_session, sql, &pset );
}
Remark-----
Either DBPROP_CLIENTCURSOR or DBPROP_IRowsetScroll property is surpported,the count of columns will be equal to actual count of columns + 1.The column 0 is used for bookmark.
HRESULT GetColumnInfo(CDataConnection& con,const CComBSTR& sql)
{
CCommand<CDynamicAccessor> rs;
CDBPropSet pset( DBPROPSET_ROWSET );
bool b=pset.AddProperty( DBPROP_ISequentialStream, true, DBPROPOPTIONS_OPTIONAL );
b=pset.AddProperty( DBPROP_IStream, true, DBPROPOPTIONS_OPTIONAL );
b=pset.AddProperty( DBPROP_CANFETCHBACKWARDS, true, DBPROPOPTIONS_OPTIONAL );
b=pset.AddProperty( DBPROP_CANSCROLLBACKWARDS, true, DBPROPOPTIONS_OPTIONAL );
b=pset.AddProperty(DBPROP_IRowsetScroll,true,DBPROPOPTIONS_OPTIONAL);
b=rs.SetBlobHandling( DBBLOBHANDLING_SKIP );
HRESULT hr=rs.Open(con, sql, &pset );
if(hr!=S_OK)
{
return hr;
}
DBTYPE dbtype;
for( DBORDINAL col = 1; col <= rs.GetColumnCount(); col++ )
{
hr=rs.GetColumnType( col, &dbtype );
if( col > 1 )
printf( ", " );
printf( "%S [%d]", rs.GetColumnName( col ), dbtype );
}
DBORDINAL count;
DBCOLUMNINFO* pInfo=NULL;
OLECHAR* pbuffer=NULL;
CComPtr<IColumnsInfo> spColumnsInfo;
rs.m_spRowset->QueryInterface(&spColumnsInfo);
if (SUCCEEDED(hr))
{
hr = spColumnsInfo->GetColumnInfo(&count, &pInfo, &pbuffer);
if(hr!=S_OK)
{
return hr;
}
}
CComPtr<IMalloc> spMalloc;
hr=CoGetMalloc(1,&spMalloc);
spMalloc->Free(pInfo);
spMalloc->Free(pbuffer);
}
HRESULT GetRowsetSize(CDataConnection& con,const CComBSTR& sql,unsigned long& size)
{
CCommand<CDynamicAccessor> rs;
CDBPropSet pset( DBPROPSET_ROWSET );
bool b=pset.AddProperty( DBPROP_ISequentialStream, true, DBPROPOPTIONS_OPTIONAL );
b=pset.AddProperty( DBPROP_IStream, true, DBPROPOPTIONS_OPTIONAL );
b=pset.AddProperty( DBPROP_CANFETCHBACKWARDS, true, DBPROPOPTIONS_OPTIONAL );
b=pset.AddProperty( DBPROP_CANSCROLLBACKWARDS, true, DBPROPOPTIONS_OPTIONAL );
b=pset.AddProperty(DBPROP_IRowsetScroll,true,DBPROPOPTIONS_OPTIONAL);
b=rs.SetBlobHandling( DBBLOBHANDLING_SKIP );
HRESULT hr=rs.Open(con, sql, &pset );
if(hr!=S_OK)
{
return hr;
}
return rs.GetApproximatePosition(NULL,NULL,&size);
}
HRESULT ExecuteSQLStatement(CDataConnection& con,const CComBSTR& sql)
{
CCommand<CNoAccessor,CNoRowset> rs;
CDBPropSet pset( DBPROPSET_ROWSET );
return rs.Open(con.m_session, sql, &pset );
}
If we want to make our db_table attribute class provide the ability of updating its fields’s values,we should pay attention to thus points:
1)Implementing the inner codes
void GetRowsetProperties(CDBPropSet* pPropSet)
{
pPropSet->AddProperty(DBPROP_CANFETCHBACKWARDS, true, DBPROPOPTIONS_OPTIONAL);
pPropSet->AddProperty(DBPROP_CANSCROLLBACKWARDS, true, DBPROPOPTIONS_OPTIONAL);
pPropSet->AddProperty(DBPROP_IRowsetUpdate,true,DBPROPOPTIONS_OPTIONAL);
pPropSet->AddProperty(DBPROP_IRowsetChange, true, DBPROPOPTIONS_OPTIONAL);
pPropSet->AddProperty(DBPROP_UPDATABILITY, DBPROPVAL_UP_CHANGE);
}
2)The codes of client
#include "stdafx.h"
#include "sender.h"
int _tmain(int argc, _TCHAR* argv[])
{
::CoInitialize(NULL);
Csender s;
s.OpenAll();
HRESULT hr=s.MoveFirst();
s.m_com_num=11;
s.SetData();
hr=s.UpdateAll();
::CoUninitialize();
return 0;
}
SetData() member function must be called.
Please refer to the below url:
CTable_1 table;
HRESULT hr=table.OpenAll();
hr=table.MoveFirst();
table.m_a=5;
table.m_dwaStatus=DBSTATUS_S_OK;
table.m_dwaLength=4;
hr=table.Insert();
Please refer to the below url:
Please see the arctile of MSDN named as Using Multiple Accessors on a Rowset
Definition----A saved placeholder value that identifies a row in a rowset and can later be used by the consumer to retrieve that particular row.
void GetBookMark(CDataConnection& con,const CComBSTR& sql)
{
CCommand<CDynamicAccessor> rs;
CDBPropSet pset( DBPROPSET_ROWSET );
pset.AddProperty( DBPROP_ISequentialStream, true, DBPROPOPTIONS_OPTIONAL );
pset.AddProperty( DBPROP_IStream, true, DBPROPOPTIONS_OPTIONAL );
pset.AddProperty( DBPROP_CANFETCHBACKWARDS, true, DBPROPOPTIONS_OPTIONAL );
pset.AddProperty( DBPROP_CANSCROLLBACKWARDS, true, DBPROPOPTIONS_OPTIONAL );
bool b=pset.AddProperty(DBPROP_CLIENTCURSOR,true,DBPROPOPTIONS_REQUIRED);
rs.SetBlobHandling( DBBLOBHANDLING_SKIP );
HRESULT hr=rs.Open(con.m_session, sql, &pset );
DBORDINAL count=rs.GetColumnCount();
CBookmark<> firstmark;
rs.MoveFirst();
char* pV=static_cast<char*>(rs.GetValue(1));
hr=rs.GetBookmark(&firstmark);
while(S_OK==rs.MoveNext())
{
CBookmark<> bookmark;
hr=rs.GetBookmark(&bookmark);
BYTE* p=bookmark.GetBuffer();
}
hr=rs.MoveToBookmark(firstmark);
pV=static_cast<char*>(rs.GetValue(1));
}
The bookmark retrieved through upon codes is numeric bookmark,the value is equalt to the index of current row.We can also use SetBookmark memeber function set the current bookmark’s value.
void GetXMLData(CDataConnection& con,const CComBSTR& sql)
{
CCommand<CXMLAccessor> rs;
CDBPropSet pset( DBPROPSET_ROWSET );
HRESULT hr=rs.Open(con.m_session, sql, &pset );
CStringW str;
while(S_OK==rs.MoveNext())
{
rs.GetXMLRowData(str,true);
}
}
void ConnectDatabase(LPTSTR conString)
{
CComBSTR str(L"Provider=MSDASQL.1;Persist Security Info=True;");
str+=conString;
CDataConnection con;
HRESULT hr=con.Open(str);
if(hr!=S_OK)
{
CDBErrorInfo info;
LCID lcid = ::GetUserDefaultLCID();
ULONG records;
hr=info.GetErrorRecords(con.m_source.m_spInit,__uuidof(IDBInitialize),&records);
CComBSTR errorMsg,source;
hr=info.GetAllErrorInfo(0,lcid,&errorMsg,&source);
string s("Failed connect to database: ");
s+=CW2A(errorMsg.m_str);
throw CTXDatabaseExcep(hr,s);
}
}
void ThrowDBException(const string& context)
{
CDBErrorInfo info;
LCID lcid = ::GetUserDefaultLCID();
ULONG records;
HRESULT hr=info.GetErrorRecords(m_con.m_source.m_spInit,__uuidof(IDBInitialize),&records);
if(hr!=S_OK)
{
throw std::runtime_error("CDBErrorInfo::GetErrorRecords faield");
}
CComBSTR errorMsg,source;
hr=info.GetAllErrorInfo(0,lcid,&errorMsg,&source);
if(hr!=S_OK)
{
throw std::runtime_error("CDBErrorInfo::GetAllErrorInfo faield");
}
string s=context+" : ";
s+=CW2A(errorMsg.m_str);
throw std::exception(s.c_str());
}
How can I use native client?Just setting the udl property,and using native client provider.
When I fetch 10,000 records ,and each record has 118 columns,Native Client provider is faster than OLE DB provider.That’s my test function.
DWORD PerformanceTest(CDataConnection& con,const CComBSTR& sql)
{
DWORD x=GetTickCount();
CCommand<CDynamicAccessor> rs;
CDBPropSet pset( DBPROPSET_ROWSET );
pset.AddProperty( DBPROP_ISequentialStream, true, DBPROPOPTIONS_OPTIONAL );
pset.AddProperty( DBPROP_IStream, true, DBPROPOPTIONS_OPTIONAL );
pset.AddProperty( DBPROP_CANFETCHBACKWARDS, true, DBPROPOPTIONS_OPTIONAL );
pset.AddProperty( DBPROP_CANSCROLLBACKWARDS, true, DBPROPOPTIONS_OPTIONAL );
bool b=pset.AddProperty(DBPROP_CLIENTCURSOR,true,DBPROPOPTIONS_REQUIRED);
rs.SetBlobHandling( DBBLOBHANDLING_SKIP );
rs.Open(con.m_session, sql, &pset );
while(S_OK==rs.MoveNext())
{}
return GetTickCount()-x;
}
OLE DB provider always spend 2,000 million seconds at least,and Native Client always spend less than 1,790 million seconds.
CREATE PROCEDURE test AS
delete from carInfo2
GO
HRESULT CallStoredProcedureNoParameterNoResult(CDataConnection& con,const CComBSTR& procName)
{
CCommand<CDynamicAccessor> rs;
CDBPropSet pset;
return rs.Open(con.m_session, procName, &pset );
}
CREATE PROCEDURE test2AS
select * from carInfo2
GO
HRESULT CallStoredProcedureNoParameter(CDataConnection& con,const CComBSTR& procName)
{
CCommand<CDynamicAccessor> rs;
CDBPropSet pset( DBPROPSET_ROWSET );
bool b=pset.AddProperty( DBPROP_ISequentialStream, true, DBPROPOPTIONS_OPTIONAL );
b=pset.AddProperty( DBPROP_IStream, true, DBPROPOPTIONS_OPTIONAL );
b=pset.AddProperty( DBPROP_CANFETCHBACKWARDS, true, DBPROPOPTIONS_OPTIONAL );
b=pset.AddProperty( DBPROP_CANSCROLLBACKWARDS, true, DBPROPOPTIONS_OPTIONAL );
b=pset.AddProperty(DBPROP_IRowsetScroll,true,DBPROPOPTIONS_OPTIONAL);
b=pset.AddProperty(DBPROP_CLIENTCURSOR,true,DBPROPOPTIONS_OPTIONAL);
HRESULT hr=rs.Open(con.m_session, procName, &pset );
if(S_OK==hr)
{
DBCOUNTITEM count(0);
hr=rs.GetApproximatePosition(0,0,&count);
return hr;
}
else
{
return hr;
}
}
CREATE PROCEDURE test3 @id int
AS
delete from carInfo2
where carID=@id
GO
HRESULT CallStoredProcedureNoRowset(CDataConnection& con,const int parameter)
{
CCommand<CDynamicParameterAccessor,CNoRowset> rs;
HRESULT hr = rs.Create(con.m_session,"exec test3 ?");
hr=rs.Prepare();
void* p;
rs.BindParameters(&rs.m_hParameterAccessor,rs.m_spCommand,&p);
bool r=rs.SetParam<int>(1,¶meter);
return rs.Open(NULL,NULL,0);
}
CREATE PROCEDURE test4 @id int
as
select * from carInfo2
select * from carInfo2
where carID=@id
GO
HRESULT CallStoredProcedure(CDataConnection& con,const int parameter)
{
CCommand<CDynamicParameterAccessor,CRowset> rs;
HRESULT hr = rs.Create(con.m_session,"exec test4 ?");
hr=rs.Prepare();
void* p;
rs.BindParameters(&rs.m_hParameterAccessor,rs.m_spCommand,&p);
bool r=rs.SetParam<int>(1,¶meter);
CDBPropSet pset( DBPROPSET_ROWSET );
bool b=pset.AddProperty( DBPROP_ISequentialStream, true, DBPROPOPTIONS_OPTIONAL );
b=pset.AddProperty( DBPROP_IStream, true, DBPROPOPTIONS_OPTIONAL );
b=pset.AddProperty( DBPROP_CANFETCHBACKWARDS, true, DBPROPOPTIONS_OPTIONAL );
b=pset.AddProperty( DBPROP_CANSCROLLBACKWARDS, true, DBPROPOPTIONS_OPTIONAL );
b=pset.AddProperty(DBPROP_IRowsetScroll,true,DBPROPOPTIONS_OPTIONAL);
b=pset.AddProperty(DBPROP_IRowsetUpdate,true,DBPROPOPTIONS_OPTIONAL);
b=pset.AddProperty(DBPROP_IRowsetChange, true, DBPROPOPTIONS_OPTIONAL);
hr=rs.Open(&pset);
hr=rs.MoveFirst();
DBORDINAL l=1;
int* pv=(int*)rs.GetValue(l);
return hr;
}
相关推荐
using System.Data.OleDb; ... string connectionString = "Provider=MySql.OleDb.1;Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;"; using (var connection = new ...
The ATL OLE DB Provider templates only seem to support read-only rowsets and making them support updating of data isn’t as easy as you’d expect!只读数据库模板
OLEDB(Object Linking and Embedding, Database)驱动程序是一种数据访问接口,它允许应用程序以统一的方式访问多种数据源,包括数据库、文件系统、Web服务等。在本话题中,我们将深入探讨“OLEDB驱动程序大全”中...
【Microsoft.ACE.OLEDB.12.0-提供程序】本资源是C#程序使用OleDb读取Excel时必备的驱动程序——Microsoft.ACE.OLEDB.12.0的提供程序。OleDb是一个数据库驱动接口,能够通过标准的 SQL 语句访问多种数据库,包括 ...
标题 "Microsoft.ACE.OLEDB.12.0" 指的是 Microsoft Office 兼容性包中的一个组件,它是用于连接和访问 Excel、Access 和其他 Office 文件的数据提供程序。这个提供程序允许开发者通过 OLEDB(对象链接和嵌入数据库...
**OLE DB 教程** OLE DB(Object Linking and Embedding, Database)是微软提出的一种数据库访问技术,它提供了一种标准的接口,使得应用程序能够访问各种数据源,包括关系数据库、文件系统、电子邮件存储等。OLE ...
OLEDB(Object Linking and Embedding, Database)是微软提出的一种数据访问接口,它允许应用程序通过统一的方式访问各种数据源,包括数据库、文件系统、Web服务等。在本主题中,我们将深入探讨“OLEDB驱动程序大全...
解决microsoft.ace.oledb.12.0连接失败所需要的驱动 完整版.zip 解决microsoft.ace.oledb.12.0连接失败所需要的驱动 完整版.zip 解决microsoft.ace.oledb.12.0连接失败所需要的驱动 完整版.zip 解决microsoft.ace....
### OLE DB(OLEDB)介绍 #### 一、OLE技术概述 OLE(Object Linking and Embedding),即对象链接与嵌入,是一项由微软公司开发的重要技术标准,旨在为不同应用程序之间提供一种通用的数据交互方式。这项技术的...
标题"Msoft.ace.oledb.12.0 x64"指的是Microsoft Access Database Engine 12.0的64位版本,这是一个重要的组件,主要用于在Windows操作系统中连接和操作Access数据库文件(.mdb和.accdb格式)。"oledb"是OLE DB...
在IT领域,数据库管理和数据迁移是常见的操作,而"ACE.OLEDB.12.0 _32和64.rar"这个压缩包文件显然与这一主题相关。标题和描述指出的问题,是用户在尝试使用ACE OLEDB 12.0提供程序时遇到的注册错误。下面将详细解释...
**Microsoft OLE DB Provider for Visual FoxPro 9.0** 是一个数据访问接口,它允许开发者通过OLE DB技术与Visual FoxPro 9.0数据库进行交互。OLE DB(Object Linking and Embedding, Database)是微软提供的一种...
- 开发者可以通过编写 OLE DB Consumer 应用程序或者使用支持 OLE DB 的组件(如 ADO)来间接访问 DM 数据库。 #### 四、DMOLEDB 编程步骤详解 ##### 1. 初始化 COM 环境 由于 OLE DB 基于 COM 技术,因此在使用...
标题 "microsoft.ace.oledb.12.0.rar" 涉及的是Microsoft Office Access连接引擎的一个版本,这是用于读写Access数据库文件(.mdb和.accdb)的组件。在描述中提到,这个压缩包是为了解决“microsoft.ace.oledb.12.0...
### Oracle Provider for OLE DB 开发者指南知识点详解 #### 一、概述 《Oracle Provider for OLE DB Developer's Guide》是一本针对Oracle数据库与OLE DB接口开发的技术文档。本书详细介绍了如何通过OLE DB...
C#报"本地未注册Microsoft.Jet.OLEDB.4.0" 及 "未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”提供程序的解决方法
《Oracle Provider for OLE DB Developer’s Guide 11g Release 2 (11.2) for Microsoft Windows》是Oracle公司为开发人员提供的一份详细指南,用于在Windows 64位环境中利用Oracle Provider for OLE DB接口进行...
using System.Data.OleDb; class ExcelOperations { public static void ReadExcelFile(string filePath) { string connectionString = $"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={filePath};Extended ...