Chinaunix首页 | 论坛 | 博客
  • 博客访问: 536578
  • 博文数量: 576
  • 博客积分: 40000
  • 博客等级: 大将
  • 技术积分: 5020
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-13 14:47
文章分类

全部博文(576)

文章存档

2011年(1)

2008年(575)

我的朋友

分类:

2008-10-14 14:56:52

使用ADO封装类的数据库程序开发实例[第二版] (上)
作者:



从上次在发表一文后,得到许多网友的响应,甚觉欣慰。但由于我对ADO也非完全精通,所以上次写的类很不完美,甚至可能给某些朋友带来麻烦,因此一直想把它写得更完善一点。

现在写的这个类功能应该说比较完善了,基本上封装了ADO组件的大部分方法,并扩展了一些人们常用到的方法,如把文件或图片写到数据库中,从数据库中读出位图字段,字段的值的智能转换等等。

因为实在是时间不够,我几乎没有对command类做任何有效的测试,也没有写相关的文档,而对connection和recordset类的文档,也写得不甚明了,也许有人又要说我很不负责任了。呵呵!

在这个测试程序中,我对连接类和记录集类的大部分方法进行了测试,包括对常用数据类型的存取,添加删除等等,还有对多种数据类型以整型,双精度型,字符型类型的变量读取,其中以字符型兼容性最好,基本上对大部分数据都能返回有效值,其次是双精度型,和整型,它们不能读取字符型,日期型等字段的值. 另外对这两个象的属性进行了一些测试,当然有好多属性是没法全面测试得到的。

我在开发ADO相关程序中切身体会到有几个方法是很有用的方法,如SetFilter,SetSort,Find,书签等等,它们可以让你很有效的操纵记录,而不用老去想怎样去构建SQL语句来实现这样功能。

其中还有一个导入导出xml文件的方法,我不知道这个方法是不是很有用,因为它对中文支持不是很好,导出的xml文件中没法正常显示中文.
最后还一个就是datagrid控件与记录集绑定,我觉得这应该是一个比较有用的技巧,我以前都没想到过,在VC中也可以学VB一样绑定数据库的,这样不用写什么代码就可以方便地修改数据了。

代码在(vc6 + sp5) / vc7 + windows XP 英文专业版/ windows 2000 中文专业版/ windows 2003 英文测试版 /windows 2003 中文企业版下编译通过, 并在access, sqlserver, mysql下进行了测试,除mysql不支持事务等方法外,大部分方法都可以通过测试.
在原则上,我默许您自由地使用,修改,或传播此代码,但您要是用在某某项目中或用于商业用途,那请您注意了,我不会对因代码bug问题,或版权问题对您造成的损失负任何责任。
由于初次封装如此多又不是很熟悉的东西,有什么不当之处还请大家多指教.

本文代码运行效果图如下:


下面详细介绍这几个封装类:

CAdoConnection class

类成员:

构造函数: CAdoConnection()
创建Connection对象.

Open 方法:

BOOL CAdoConnection::Open(LPCTSTR lpszConnect, long lOptions)
连接到数据源.

Params:
[lpszConnect]: 连接字符串, 包含连接信息.
[lOptions]: 可选. 决定该方法是以同步还是异步的方式连接数据源. 可以是如下某个常量:

[常量] [说明]
adConnectUnspecified (默认)同步方式打开连接.
adAsyncConnect 异步方式打开连接.
Ado用 ConnectComplete 事件来通知已经完成连接.

BOOL CAdoConnection::ConnectSQLServer(CString dbsrc, CString dbname, CString user, CString pass, long lOptions)
连接到 SQL Server 数据库.

BOOL CAdoConnection::ConnectAccess(CString dbpath, CString pass, long lOptions)
连接到 Access 数据库.

Params:
[dbpath]: Access MDB 数据库文件路径名.
[pass]: 访问密码.
[dbsrc]: SQL SERVER 服务器名.
[dbname]: 默认的数据库名.
[user]: 用户名.

OpenUDLFile方法:

BOOL CAdoConnection::OpenUDLFile(LPCTSTR strFileName, long lOptions)
通过打开udl文件连接数据库.

Params:
[strFileName]: UDL 数据库连接文件路径名.

// 访问SQL Server 的例子:

CAdoConnection pAdoConnection;
CString strConnection = _T("Provider=SQLOLEDB.1;Persist Security Info=False;"
			"Integrated Security=SSPI;"
			"Data Source=cz\\xyy;Initial Catalog=NoteBook;");
if (pAdoConnection.Open(LPCTSTR(strConnection)))
{
	DoSomething();
}
...
或者:
if (pAdoConnection.ConnectSQLServer("cz\\xyy", "NoteBook", "sa", "007"))
{
	DoSomething();
}

//访问 ACCESS 的例子:
CAdoConnection pAdoConnection;
CString strConnection = _T("Provider=Microsoft.Jet.OLEDB.4.0;"
			   "Data Source=C:\\dbTest.mdb");
pAdoDb.SetConnectionString(strConnection);

if (pAdoConnection.Open(LPCTSTR(strConnection)))
{
	DoSomething();

}
...

或者:
if (pAdoConnection.ConnectAccess("C:\\dbTest.mdb", "007"))
{
	DoSomething();
}
...

Close 方法:
void CAdoConnection::Close()
关闭与数据源的连接.
Remarks: 使用 Close 方法可关闭 Connection 对象以便释放所有关联的系统资源. 关闭对象并非将它从内存中删除, 可以更改它的属性设置并且在此后再次打开. 在超出 Connection 对象作用域或重新连接新的数据库时会自动调用此方法.

Execute 方法:
_RecordsetPtr CAdoConnection::Execute(LPCTSTR lpszSQL, long lOptions)
执行指定的查询、SQL 语句、存储过程等.
Remarks: 请参考 CAdoRecordSet 类的Open方法. 返回的 Recordset 对象始终为只读、仅向前的游标. 连接对象的此方法一般用来执行一些不用返回记录集的SQL语句. 不需要为了执行一条小语句而动用RecordSet对象,显得更为灵活点.

如:

if (pAdoConnection.IsOpen())
{
	pAdoConnection.Execute("Delete From student Where number = 3");
}
Cancel 方法:
BOOL CAdoConnection::Cancel()
Remarks: 请参考 CAdoRecordSet 类 Cancel 方法.

GetLastErrorText 方法:
CString CAdoConnection::GetLastErrorText()
取得最后发生的错误信息.
Remarks: 任何涉及 ADO 对象的操作都可以产生一个或多个提供者错误. 产生错误时,可以将一个或多个 Error 对象置于 Connection 对象的 Errors 集合中. 其他 ADO 操作产生错误时, 将清空 Errors 集合, 并且将新的 Error对象置于 Errors 集合中.每个 Error 对象代表特定的提供者错误, 而不是 ADO 错误. ADO 错误被记载在运行时的异常处理机制中.没有产生错误的 ADO 操作对 Errors 集合没有影响. 使用 Clear 方式可手工清除 Errors 集合.

ErrorsPtr CAdoConnection::GetErrors()
获得错误集对象指针.

ErrorPtr CAdoConnection::GetError(long index)
获得错误对象指针.

IsOpen 属性:
BOOL CAdoConnection::IsOpen()
检测连接对象是否为打开状态.

ConnectTimeOut 属性:
BOOL CAdoConnection::SetConnectTimeOut(long lTime)
long CAdoConnection::GetConnectTimeOut()
设置或取得连接超时时间.

ProviderName 属性:
CString CAdoConnection::GetProviderName()
取得 Connection 对象提供者的名称.

Version 属性:
CString CAdoConnection::GetVersion()
取得当前使用的 ADO 的版本号

State 属性:
long CAdoConnection::GetState()
取得对象的状态(同 Recordset 对象的 GetState 方法).
returns: 返回下列常量之一的长整型值(连接对象一般为下面两种状态之一).

[常量] [说明]
adStateClosed 指示对象是关闭的.
adStateOpen 指示对象是打开的.

Remarks: 可以随时使用 State 属性取得指定对象的当前状态.

Mode 属性:
ConnectModeEnum CAdoConnection::GetMode()
BOOL CAdoConnection::SetMode(ConnectModeEnum mode)
设置或取得在 Connection 对象中修改数据的可用权限.
returns: 返回以下某个 ConnectModeEnum 的值.

[常量] [说明]
adModeUnknown 默认值. 表明权限尚未设置或无法确定.
adModeRead 表明权限为只读.
adModeWrite 表明权限为只写.
adModeReadWrite 表明权限为读/写.
adModeShareDenyRead 防止其他用户使用读权限打开连接.
adModeShareDenyWrite 防止其他用户使用写权限打开连接.
adModeShareExclusive 防止其他用户打开连接.
adModeShareDenyNone 防止其他用户使用任何权限打开连接.

Remarks: 使用 Mode 属性可设置或返回当前连接上提供者正在使用的访问权限. 只能在关闭 Connection 对象时方可设置 Mode 属性.

OpenSchema 方法:

_RecordsetPtr CAdoConnection::OpenSchema(SchemaEnum QueryType)
从数据源获取数据库信息.

Params: [QueryType]: 所要运行的模式查询类型, 下面列出一些较常用的类型及返回的表中多条字段中主要的字段名.

adSchemaAsserts CONSTRAINT_NAME
adSchemaCatalogs CATALOG_NAME
adSchemaCharacterSets CHARACTER_SET_NAME
adSchemaCheckConstraints CONSTRAINT_NAME
adSchemaCollations COLLATION_NAME
adSchemaColumnDomainUsage DOMAIN_NAME
  COLUMN_NAME
adSchemaColumnPrivileges TABLE_NAME
  COLUMN_NAME
  GRANTOR
  GRANTEE
adSchemaColumns TABLE_NAME
  COLUMN_NAME
adSchemaConstraintColumnUsage TABLE_NAME
  COLUMN_NAME
adSchemaConstraintTableUsage TABLE_NAME
adSchemaForeignKeys PK_TABLE_NAME
  FK_TABLE_CATALOG
  FK_TABLE_SCHEMA
  FK_TABLE_NAME
adSchemaIndexes INDEX_NAME
  TYPE
  TABLE_NAME
adSchemaKeyColumnUsage CONSTRAINT_NAME
  TABLE_CATALOG
  TABLE_SCHEMA
  TABLE_NAME
  COLUMN_NAME
adSchemaPrimaryKeys PK_TABLE_NAME
adSchemaProcedureColumns PROCEDURE_NAME
  COLUMN_NAME
adSchemaProcedureParameters PROCEDURE_NAME
  PARAMTER_NAME
adSchemaProcedures PROCEDURE_NAME
  PROCEDURE_TYPE
adSchemaProviderSpecific 参见说明
adSchemaProviderTypes DATA_TYPE
  BEST_MATCH
adSchemaReferentialConstraints CONSTRAINT_NAME
adSchemaSchemata SCHEMA_OWNER
adSchemaSQLLanguages <无>
adSchemaStatistics TABLE_NAME
adSchemaTableConstraints CONSTRAINT_NAME
  TABLE_CATALOG
  TABLE_SCHEMA
  TABLE_NAME
  CONSTRAINT_TYPE
adSchemaTablePrivileges TABLE_NAME
  GRANTOR
  GRANTEE
adSchemaTables TABLE_NAME
  TABLE_TYPE
adSchemaTranslations TRANSLATION_NAME
adSchemaUsagePrivileges OBJECT_NAME
  OBJECT_TYPE
  GRANTOR
  GRANTEE
adSchemaViewColumnUsage VIEW_NAME
adSchemaViewTableUsage VIEW_NAME
adSchemaViews VIEW_NAME

returns: 返回包含数据库信息的 Recordset 对象. Recordset 将以只读、静态游标打开.
Remarks: OpenSchema方法返回与数据源有关的信息, 例如关于服务器上的表以及表中的列等信息, 上述数据仅供参考, 视具体的数据源可能会有不同.


Trans 相关方法:
long CAdoConnection::BeginTrans()
BOOL CAdoConnection::CommitTrans()
BOOL CAdoConnection::RollbackTrans()
BeginTrans - 开始新事务.
CommitTrans - 保存任何更改并结束当前事务.它也可能启动新事务.
RollbackTrans - 取消当前事务中所作的任何更改并结束事务. 它也可能启动新事务.

一旦调用了 BeginTrans 方法, 在调用 CommitTrans 或 RollbackTrans 结束事务之前, 数据库将不再立即提交所作的任何更改.
对于支持嵌套事务的数据库来说, 在已打开的事务中调用 BeginTrans 方法将开始新的嵌套事务. 返回值将指示嵌套层次: 返回值为 1 表示已打开顶层事务(即事务不被另一个事务所嵌套), 返回值为 2 表示已打开第二层事务(嵌套在顶层事务中的事务), 依次类推. 调用 CommitTrans 或 RollbackTrans 只影响最新打开的事务;在处理任何更高层事务之前必须关闭或回卷当前事务.
调用 CommitTrans 方法将保存连接上打开的事务中所做的更改并结束事务. 调用 RollbackTrans方法还原打开事务中所做的更改并结束事务. 在未打开事务时调用其中任何一种方法都将引发错误.

// 数值类型转换 -----------------------------------
COleDateTime vartodate(const _variant_t& var);
COleCurrency vartocy(const _variant_t& var);
bool vartobool(const _variant_t& var);
BYTE vartoby(const _variant_t& var);
short vartoi(const _variant_t& var);
long vartol(const _variant_t& var);
double vartof(const _variant_t& var);
CString vartostr(const _variant_t& var);
把变体型变量转换成其他类型变量.


--------------------next---------------------

为什么我用的你Execute就是建不了表格啊~??? ( livedeal 发表于 2007-4-21 17:25:00)
 
dll能用找到原因了,原来和dao有关 ( yhaiquan 发表于 2005-11-15 16:12:00)
 
在MFC 写的DLL中不行 ( yhaiquan 发表于 2005-11-15 15:54:00)
 
这是一个不错的 ADO 封装类,非常感谢作者
在使用中发现一个问题:
在函数
BOOL CAdoRecordSet::GetChunk(FieldPtr pField, LPVOID lpData)
中有一句:
while (index < pField->ActualSize)
改成:
long len = pField->ActualSize;
while (index < len)
才能成功读取 Image 类型数据 (SQL Server)

( hloveloveu 发表于 2004-7-27 10:34:00)
 
连接access数据库有个bug,数据库加密码就访问不了;
CString strConnect = _T("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=") + dbpath;
应改为:
CString strConnect = _T("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=") + dbpath+";";

( autism 发表于 2004-5-17 13:17:00)
 
欢迎加盟中国微型软件开发中心,网站正建设中。。。
为你量身定做各种小型软件,

联系方式:
email:ldh5118@sohu.com
qq   : 36201365 ( rbird5118 发表于 2004-4-14 16:02:00)
 
欢迎加盟中国微型软件开发中心,网站正建设中。。。
为你量身定做各种小型软件,

联系方式:
email:ldh5118@sohu.com
qq   : 36201365 ( rbird5118 发表于 2004-4-14 15:58:00)
 
tigeroar:想请各位帮个忙,不过我在调用过程中有几处出错,因为我对ADO不熟,我也不知道是什么原因.
一处是

这里只是对表进行更新.

CAdoRecordSet pRecordSet;
pRecordSet.SetAdoConnection(m_pConnection);
pRecordSet.SetCursorLocation();

queryStr = "select * from "+m_TableName;

pRecordSet.Open(queryStr);
pRecordSet.SetSort("位数 ASC");

pRecordSet.MoveFirst();
const int AllLoc = 2;
for(i=0;i{
if( 
pRecordSet.PutCollect("年龄",m_Age
)
flag++;
}

pRecordSet.Close();
在关闭时会出抛出异常.

Warning: UpdateBatch 方法发生异常. 错误信息: Unknown error 0x800A0BCD; 文件: E:\vcproject\CarCheckSI\AdoRecordSet.cpp; 行: 895
Warning: UpdateBatch 方法发生异常. 错误信息: Unknown error 0x800A0BCD; 文件:  Exception.
First-chance exception in CarCheck.exe (KERNEL32.DLL): 0xE06D7363: Microsoft C++ Exception.


非常感谢你的代码,也谢谢你能帮我解决这些问题!

(发表于2003-11-14 18:29:00)

( tigeroar 发表于 2003-11-14 18:31:00)
 
我在把日期型数据转换成CString 型时总是出错,为什么?
m_pSet->GetFieldValue(index,var);
const VARIANT* variant = LPVARIANT(var);
COleDateTime t(variant->date);
str=t.Format("%Y %m %d");//此步出错
请指点指点把!急等佳音. ( zhawei 发表于 2003-9-11 21:00:00)
 
谢谢你的类。
有问题请教,请问为什么在console模式下不能连接
数据库,而同样的代码是能在Dialog下运行的,
能指点一下吗 ( jfu_router 发表于 2003-6-25 12:39:00)
 
.......................................................

--------------------next---------------------

阅读(311) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~