大手大脚之数据库使用基本篇 响应bluebohe,开始提问:在Win下常用到哪些数据库?各自的特点,背景?各类数据库的基本安装/配置方法?使用VC如何与各类数据库连接,如何进行基本的建表,读取,回存?实例? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 用代码实现自动注册一个工程目录下的access数据库的ODBC数据源:CString sPath;GetModuleFileName(NULL,sPath.GetBufferSetLength(MAX_PATH+1),MAX_PATH);//得到程序的路径sPath.ReleaseBuffer ();int nPos;nPos=sPath.ReverseFind('\\');sPath=sPath.Left(nPos);nPos=sPath.ReverseFind('\\');sPath=sPath.Left(nPos);CString lpszFile=sPath+"\\lhwy.mdb"; //得到程序目录下的数据库的完整路径 char* szDesc;int mlen;szDesc=new char[256];sprintf(szDesc,"DSN=%s? DESCRIPTION=TOC support source? DBQ=%s? FIL=MicrosoftAccess? DEFAULTDIR=%s??","lhwy",lpszFile,sPath); //形成一个SQLConfigDataSource函数参数串结构mlen = strlen(szDesc);for (int i=0; i<mlen; i++){ if(szDesc[i]=='?') szDesc[i] = '\0'; //替换上面串的?为\0,形成一个完整的串}if (FALSE == SQLConfigDataSource(NULL,ODBC_ADD_DSN,"Microsoft Access Driver (*.mdb)\0",(LPCSTR)szDesc))//注册数据库 AfxMessageBox("SQLConfigDataSource Failed"); 转帖: http://www.vccode.com/file_show.php?id=202从功能简单的数据库(如Jet Engine)到复杂的大型数据库系统(如oracle),VC++6.0都提供了一些编程接口。本文主要介绍以下五种: 1.ODBC API; 2.MFC ODBC类; 3.MFC DAO类;(数据访问对象) 4.MFC的OLE/DB; 5.ActiveX数据对象(ADO)。 1.开放数据库连接(ODBC API):提供了一个通用的编程接口,允许程序与多种不同的数据库连接。它为Oracle,SQL Server,MS Excel等都提供了驱动程序,使得用户可以使用SQL语句对数据库进行直接的底层功能操作。在使用ODBC API时,用户须引入的头文件为"sql.h","sqlext.h","sqltypes.h"。用ODBC API创建数据库应用程序遵循一定的基本步骤: 第一步是分配ODBC环境,使一些内部结构初始化。完成这一步,须分配一个SQLHENV类型的变量在ODBC环境中做句柄使用。 第二步是为将要使用的每一个数据源分配一个连接句柄,由函数SQLALLocHandle()完成。 第三步是使用SQLConnect()把连接句柄与数据库连接,可以先通过SQLSetConnectAttr()设置连接属性。 然后就可以进行SQL语句的操作,限于篇幅,相关的函数就不具体介绍了,读者可以参考相关书籍。 操作完成后,用户取回相应的结果,就可以取消与数据库的连接。 最后需要释放ODBC环境。 ODBC API的特点是功能强大丰富,提供了异步操作,事务处理等高级功能,但相应的编程复杂,工作量大。 2.MFC ODBC类:MFC1.5后的版本里引入封装了ODBC功能的类。通过这些类提供与ODBC的接口,使得用户可以不须处理ODBC API中的繁杂处理就可以进行数据库操作。主要的MFC ODBC类如下。 CDatabase类:一个CDatabase对象表示一个到数据源的连接,通过它可以操作数据源。应用程序可使用多个CDatabase对象:构造一个对象并调用OpenEx()成员函数打开一个连接。接着构造CRecordSet对象以操作连接的数据源,并向CDatabase对象传递记录集构造程序指针。完成使用后用Close()成员函数销毁CDatabase对象。一般情况下并不需要直接使用CDatabase对象,因为CRecordSet对象可以实现大多数的功能。但是在进行事务处理时,CDatabase就起到关键作用。事务(Transaction)指的是将一系列对数据源的更新放在一起,同时提交或一个也不提交,为的是确保多用户对数据源同时操作时的数据正确性。 CRecordSet类:一个CRecordSet对象代表一个从数据源选择的一组记录的集合-记录集。记录集有两种形式:snapshot和dynaset。前者表示数据的静态视图,后者表示记录集与其他用户对数据库的更新保持同步。通过CRecordSet对象,用户可以对数据库中的记录进行各种操作。 CRecordView类:CRecordView对象是在空间中显示数据库记录的视图。这种视图是一种直接连到一个CRecordSet对象的格式视图,它从一个对话框模板资源创建,并将CRecordSet对象的字段显示在对话框模板的控件里。对象利用DDX和RFX机制,使格式上的控件和记录集的字段之间数据移动自动化,也就是说,用户甚至不要编写一行代码就可以实现简单的数据库记录查看程序。 CDBException类:由Cexception类派生,以三个继承的成员变量反映对数据库操作时的异常: m_nRetCode:以ODBC返回代码(SQL_RETURN)的形式表明造成异常的原因。 m_strError:字符串,描述造成抛出异常的错误原因。 m_strStateNativeOrigin:字符串,用以描述以ODBC错误代码表示的异常错误。 MFC数据库类成员函数都能抛出CDBException类型的异常,所以在代码对数据库进行操作后监测异常是正确做法。 MFC ODBC类在实际开发中应用最广,因为它功能丰富,操作相对简便。 3.MFC DAO(数据访问对象)编程:DAO用于和微软的Access数据库接口。在数据库应用程序如果只需与Access数据库接口时,使用DAO编程较方便。其主要类如下。 CDaoWorkspace:CDaoWorkspace对象可以让一个用户管理从登陆到离开期间,指定的密码保护的数据库会话全过程。大多数情况下不要多个工作区也不要创建明确的工作区对象。因为在打开数据库和记录集对象时,它们可以使用DAO缺省工作区。 CDaoDatabase:代表一个连接,类似上述CDatabase类。 CDaoRecordSet:用来选择记录集并操作,类似上述CRecordSet类。 CDaoRecordView:类似上述CRecordView类。 CDaoException:类似上述CDBException类。 CDaoTableDef:表示基本表或附加表的定义。每个DAO数据库对象包括一个称为TableDef的收集,包含所有存储的DAO表定义对象。CDaoTableDef对象可以用来控制表定义。 CDaoQueryDef:CDaoQueryDef对象表示了一个查询定义(querydef)。 CDaoFieldExchange:支持数据库类使用的DAO字段交换(DFX)例程。也可处理事务,类似MFC ODBC类。 MFC DAO仅用来支持Access数据库,应用范围相对固定。 4.OLE DB:OLE DB在数据提供程序和用户之间提供了灵活的组件对象模型(COM)接口,这种灵活性有时会使得操作复杂化。OLE DB框架定义了应用的三个基本类。 数据提供程序Data Provider:拥有自己的数据并以表格形式显示数据的应用程序。提供OLE DB的行集COM接口,期显示范围可以从单一数据表格的简单提供者知道更复杂的分布式数据库系统。 使用者Consumers:使用OLE DB接口对存储在数据提供程序中的数据进行控制的应用程序。用户应用程序归为使用类。 服务提供程序Service Provider:是数据提供程序和使用者的组合。服务提供程序没有自己的数据,但使用 OLE DB使用者接口来访问存储在数据提供程序中的数据。然后,服务提供程序通过打开数据提供程序接口使得数据对使用者有效。服务提供程序常用于向应用程序提供高层次服务,比如高级分布式查询。 OLE DB编程时,用户使用组件对象开发应用程序。这些组件有: 枚举器:用于列出可用的数据源; 数据源:代表单独的数据和服务提供程序,用于创建对话; 对话:用于创建事务和命令; 事务:用于将多个操作归并为单一事务处理; 命令:用于向数据源发送文本命令(SQL),返回行集; 错误:用于获得错误信息。 5.ActiveX数据对象(ADO):是微软提供的面向对象的接口,与OLE DB类似,但接口更简单,具有更广泛的特征数组和更高程度的灵活性。ADO基于COM,提供编程语言可利用的对象,除了面向VC++,还提供面向其他各种开发工具的应用,如VB,VJ等。ADO在服务器应用方面非常有用,特别是对于动态服务器页面ASP(Active Server Page)。 ADO对象结构类似于OLE DB,但并不依靠对象层次。大多数情况下,用户只需要创建并只使用需要处理的对象。下面的对象类组成了ADO接口。 Connection:用于表示与数据库的连接,以及处理一些命令和事务。 Command:用于处理传送给数据源的命令。 Recordset:用于处理数据的表格集,包括获取和修改数据。 Field:用于表示记录集中的列信息,包括列值和其他信息。 Parameter:用于对传送给数据源的命令之间来回传送数据。 Property:用与操作在ADO中使用的其他对象的详细属性。 Error:用于获得可能发生的错误的详细信息。 在VC++使用ADO需要进行COM操作,详细方法在此就不赘述了。 在当今流行的分布式开发环境下,VC++6.0在数据库开发方面有较强的优势,学会 在不同的场合选用不同的技术,对开发人员来说是必要的技术。 ADO第一次亲密接触 -- ADO开发实践之一http://www.vckbase.com/document/viewdoc.asp?id=215使用ADO实现BLOB数据的存取 -- ADO开发实践之二http://www.vckbase.com/document/viewdoc.asp?id=252 直接通过ADO操作Access数据库http://www.vckbase.com/document/viewdoc.asp?id=496用MFC + ADO 把jpg图象文件放入ACCESS库中http://www.vckbase.com/vckbase/vckbase23/ http://my.kharkov.org/docs/oracle/nt.816/a75235/using.htm 关于sql server和oracle及sybase之间的区别:这些都是关系型数据库。比access先进得多。access是基于文件的。我个人觉得从用户角度讲sql server和oracle差不多,只是在查询性能上存在差异。由于sql语句定义是语义上的。所以各个公司自己在算法实施上有很大差异。一般的说来,oracle的要好于sql server。但是如果只有有限的几个表,几万行记录,这种差别是体现不出来的。但是oracle在建库和维护上要比sql server麻烦的多。至于sybase,他和sql server 基本一样。因为早期的sql server版本就是微软联合sybase开发的(6.6以前)。著名的数据库还有IBM DB2 如何使用ADO访问Oracle数据库存储过程?http://www.xhstudio.net/show.asp?id=2185 转载 在VC中动态加载ODBC的方法 方法一:修改注册表 设计思路 一般情况下,当用户在控制面板中配置好 ODBC数据源后, Windows系统便在注册表中加入了一些子键来存储用户的配置结果。当应用程序需要用到数据源时, Windows便会通知底层接口查阅注册表中该数据源的配置。如果用户删除了某个 ODBC数据源,那么也会在注册表中有所反应。如果配置的数据源是用户数据源, Windows系统便会修改注册表的 HKEY_CURRENT_USER\SOFTWARE\ODBC\ODBC.INI子键;如果配置的数据源是系统数据源, Windows系统便会修改注册表的 HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI主键。因此,我们可以在应用程序中使用 Windows API中的注册表编辑函数来完成 Windows所做的工作,这样就可以达到动态加载数据源的目的。 具体实现 对于不同类型的数据源,注册表的修改也各有不同,但基本上都要修改两个地方。一个是在 ODBC.INI子键下建立一个与数据源描述名同名的子键,并在该子键下建立与数据源配置相关的项;另一个是在 \ODBC.INI\ODBC Data Sources子键下建立一个新项以便告诉驱动程序管理器 ODBC数据源的类型。下面以配置一个 Microsoft Access数据源为例给出实现此功能的函数的代码。 /* strSourceName是要创建的数据源名, strSourceDb是数据库存放路径, strDescription是数据源的描述字符串。* / BOOL CLoadOdbcDlg:: LoadDbSource(CString strSourceName,CString strSourceDb, CString strDescription) { //存放打开的注册表键 HKEY hKey; DWORD dw; //存放注册表 API函数执行的返回值 LONG lReturn; //存放要打开的子键 CString strSubKey; //检测是否安装了 MS Access ODBC driver:odbcjt32.dll //获得 Windows系统目录 char sysDir[MAX_PATH]; char drvName[]=" \\odbcjt32.dll" ; ::GetSystemDirectory (sysDir,MAX_PATH); strcat(sysDir,drvName); CFileFind findFile; if(!findFile.FindFile (sysDir)) { AfxMessageBox("您的计算机系统中没有安装 MS Access的 ODBC驱动程序 odbcjt32.dll,您将无法加载该类数据源。 " ,MB_OK ¦MB_ICONSTOP); return false; } strSubKey=" SOFTWARE\\ODBC\\ODBC.INI\\"+ strSourceName; //创建 ODBC数据源在注册表中的子键 lReturn=::RegCreateKeyEx(HKEY_LOCAL_ MACHINE,(LPCTSTR)strSubKey,0,NULL,REG_OPTION _NON_VOLATILE,KEY_WRITE,NULL,& hKey,& dw); if(lReturn != ERROR_SUCCESS) return false; //设置数据源的各项参数 CString strDbq=strSourceDb; CString strDriver=sysDir; DWORD dwDriverId=25; CString strFil=" MS Access" ; CString strPwd=strSourceName; DWORD dwSafeTransactions=0; CString strUid=strSourceName; ::RegSetValueEx (hKey," DBQ" ,0L,REG_SZ, (CONST BYTE* )((LPCTSTR) strDbq),strDbq .GetLength ()) ; ::RegSetValueEx (hKey," Description" ,0L,REG_SZ,(CONST BYTE* )((LPCTSTR)strDescription),strDescription.GetLength()); ::RegSetValueEx (hKey," Driver" ,0L,REG_SZ,(CONST BYTE* )((LPCTSTR)strDriver),strDriver .GetLength ()); ::RegSetValueEx (hKey," DriverId" ,0L,REG_DWORD,(CONST BYTE* )(& dwDriverId),sizeof(dw)); ::RegSetValueEx (hKey," FIL" ,0L,REG_SZ, (CONST BYTE* )((LPCTSTR) strFil),strFil .GetLength ()); ::RegSetValueEx (hKey," PWD" ,0L,REG_SZ, (CONST BYTE* )((LPCTSTR)strPwd),strPwd.GetLength ()) ; ::RegSetValueEx (hKey," SafeTransactions" ,0L, REG_DWORD,(CONST BYTE* )(& dwSafeTransactions),sizeof(dw)); ::RegSetValueEx (hKey," UID" ,0L,REG_SZ, (CONST BYTE* )((LPCTSTR)strUid),strUid .GetLength ()); ::RegCloseKey(hKey); //创建 ODBC数据源的 Jet子键 strSubKey+ =" \\Engines\\Jet" ; lReturn=::RegCreateKeyEx (HKEY_LOCAL_MACHINE ,(LPCTSTR)strSubKey,0,NULL,REG_OPTION_NON_ VOLATILE,KEY_WRITE,NULL,& hKey,& dw); if(lReturn != ERROR_SUCCESS) return false; //设置该子键下的各项参数 CString strImplict=" " ; CString strUserCommit=" Yes" ; DWORD dwPageTimeout=5; DWORD dwThreads=3; DWORD dwMaxBufferSize=2048; ::RegSetValueEx (hKey," ImplictCommitSync" ,0L,REG_SZ,(CONST BYTE* )((LPCTSTR)strImplict),strImplict.GetLength ()+ 1); ::RegSetValueEx (hKey," MaxBufferSize" ,0L,REG_DWORD,(CONST BYTE* )(& dwMaxBufferSize),sizeof(dw)); ::RegSetValueEx (hKey," PageTimeout" ,0L,REG_DWORD,(CONST BYTE* )(& dwPageTimeout),sizeof(dw)); ::RegSetValueEx (hKey," Threads" ,0L,REG_DWORD,(CONST BYTE* )(& dwThreads),sizeof(dw)); ::RegSetValueEx (hKey," UserCommitSync" ,0L,REG_SZ,(CONST BYTE* )((LPCTSTR)strUserCommit),strUserCommit.GetLength ()); ::RegCloseKey (hKey); //设置 ODBC数据库引擎名称 lReturn=::RegOpenKeyEx (HKEY_LOCAL_MACHINE, " SOFTWARE\\ODBC\\ODBC.INI\\ODBC Data Sources" ,0L,KEY_WRITE,& hKey); if(lReturn !=ERROR_SUCCESS) return false; CString strDbType=" Microsoft Access Driver (* .mdb)" ; ::RegSetValueEx (hKey,strSourceName,0L,REG_SZ,(CONST BYTE* )((LCTSTR)strDbType),strDbType.GetLength ()); return true; } 由于在动态加载中,一般只会改变数据库文件、数据源说明以及数据源描述,故上述函数可以实现应用中的大部分要求。如果应用中还需要作更多的改变,那么也可以通过改变函数参数的方式加以实现。对于需要动态加载多种类型数据源的情况,可以用具有不同参数的重载函数去实现。 方法二:利用 DLL 设计思路 Windows系统子目录中的动态链接库 Odbcinst.dll提供了一个可以动态地增加、修改和删除数据源的函数 SQLConfigDataSource()。该函数的原型如下: BOOL SQLConfigDataSource(HWND hwndParent,WORD fRequest, LPCSTR lpszDriver, LPCSTR lpszAttributes); hwndParent参数是父窗口句柄。如果该值为 NULL,将不会显示与父窗口有关的对话框。 fRequest参数可以设置为下面的数值之一: ODBC_ADD_DSN:增加一个新的用户数据源; ODBC_CONFIG_DSN:修改(配置)一个已经存在的用户数据源; ODBC_REMOVE_DSN:删除一个已经存在的用户数据源; ODBC_ADD_SYS_DSN:增加一个新的系统数据源; ODBC_CONFIG_SYS_DSN:修改 (配置 )一个已经存在的系统数据源; ODBC_REMOVE_SYS_DSN:删除一个已经存在的系统数据源。 lpszDriver参数用于传递数据库引擎的名字,等同于方法一中 strDbType变量。 lpszAttirbutes参数是关键字的值,即一连串的 " keyname=value"字符串,每两个字符串之间用 " \"隔开,如 DSN=Personnel Data\0UID=Smith\0DATABASE=Personnel。关于该参数的详细设置请参阅 MSDN中 SQLConfigDataSource()函数的帮助文档和各种 ODBC驱动程序文档。 具体实现 由于 VC的缺省库文件中不包含 SQLConfigDataSource()函数,因此使用该函数之前需要将 odbcinst.h文件包含在工程的头文件中,在工程的 Settings属性对话框 Link属性页的 Object/library modules编辑框中增加 odbc32.lib,同时保证系统目录 system32下有文件 odbccp32.dll。 仍以 Microsoft Access为例,设置数据源名为 demo,数据源描述为 "示例数据源 ",那么在需要动态加载数据源的地方加入下列代码即可: ::SQLConfigDataSource (NULL,ODBC_ADD_SYS_DSN," Microsoft Access Driver (* .mdb)"," DSN=demo\0Descirption=示例数据库 " ); 小结 上述两种方法都可以实现动态加载各种类型的 ODBC数据源,并且在 Windows95/98/NT/2000环境下调试通过。方法一在实现时需要较多的代码,方法二所需代码虽少,但需要额外文件的支持,而且随着数据源配置的灵活性的增加,为了形成 lpszAttributes字符串,其代码长度也会相应增加。由于从控制面板配置数据源使得程序员可以获得更加直观的理解,所以对于注册表中各项值以及相应项名称的获得除了可以查阅相关驱动程序的文档外,程序员也可以在编程前先通过控制面板配置 ODBC数据源,然后根据注册表中相应部分的内容进行编程 为什么以console方式运行程序可以连接odbc,而以运行服务方式不可以呢?http://community.csdn.net/Expert/topic/3166/3166638.xml?temp=.1985742---------------------------回复人: zhangshengyu(zhangshengyu) 做成服务是可以的,和应用程序一样,但是创建时必须要在参数dwServiceType中加入SERVICE_INTERACTIVE_PROCESS-----------------------------回复人: sjzxyg(小小鸟) 服务不能使用用户数据源,要使用系统数据源==============================这里当个FAQ,^_^ ADO使用ole db驱动的 数据连接属性对话框,即双击*.udl文件后打开的对话框#import "C:\\Program Files\\Common Files\\System\\Ole DB\\oledb32.dll" no_namespace _ConnectionPtr m_pConn; ...... IDataSourceLocatorPtr Locator; Locator.CreateInstance(__uuidof(DataLinks)); ::SetParent((HWND)(Locator->hWnd),this->GetSafeHwnd()); Locator->hWnd=(long)(::AfxGetMainWnd()->m_hWnd); m_pConn=Locator->PromptNew(); CString str; str=(char*)(m_pConn->ConnectionString); m_pConn->Open(_bstr_t(str),"","",adConnectUnspecified); Locator.Release(); Locator = NULL; 用c语言进行图像特殊处理编码 请教一下,回调函数为什么一定要以CALLBACK声明 请问怎么在mfc中对话框程序一运行就成为系统托盘 求教字符串资源的问题 如何在工具条上添加文本,在线等待!谢谢! 我家里不宽裕,妈妈,整天挂念我,希望我在外面好好的 一个MFC的DLL的问题 网上哪里可以找得到关于条码识别的东西 怎样快速显示bmp文件 为何无法注册窗口类啊~~~~!! 大问题:如何在2秒钟后关闭用afxmessagebox弹出的消息框? listctrl本身有排序功能吗?急!
CString sPath;
GetModuleFileName(NULL,sPath.GetBufferSetLength(MAX_PATH+1),MAX_PATH);//得到程序的路径
sPath.ReleaseBuffer ();
int nPos;
nPos=sPath.ReverseFind('\\');
sPath=sPath.Left(nPos);
nPos=sPath.ReverseFind('\\');
sPath=sPath.Left(nPos);
CString lpszFile=sPath+"\\lhwy.mdb"; //得到程序目录下的数据库的完整路径
char* szDesc;
int mlen;
szDesc=new char[256];
sprintf(szDesc,"DSN=%s? DESCRIPTION=TOC support source? DBQ=%s? FIL=MicrosoftAccess? DEFAULTDIR=%s??","lhwy",lpszFile,sPath); //形成一个SQLConfigDataSource函数参数串结构mlen = strlen(szDesc);
for (int i=0; i<mlen; i++)
{
if(szDesc[i]=='?')
szDesc[i] = '\0'; //替换上面串的?为\0,形成一个完整的串
}if (FALSE == SQLConfigDataSource(NULL,ODBC_ADD_DSN,"Microsoft Access Driver (*.mdb)\0",(LPCSTR)szDesc))//注册数据库
AfxMessageBox("SQLConfigDataSource Failed");
从功能简单的数据库(如Jet Engine)到复杂的大型数据库系统(如oracle),VC++6.0都提供了一些编程接口。本文主要介绍以下五种:
1.ODBC API;
2.MFC ODBC类;
3.MFC DAO类;(数据访问对象)
4.MFC的OLE/DB;
5.ActiveX数据对象(ADO)。
1.开放数据库连接(ODBC API):提供了一个通用的编程接口,允许程序与多种不同的数据库连接。它为Oracle,SQL Server,MS Excel等都提供了驱动程序,使得用户可以使用SQL语句对数据库进行直接的底层功能操作。在使用ODBC API时,用户须引入的头文件为"sql.h","sqlext.h","sqltypes.h"。用ODBC API创建数据库应用程序遵循一定的基本步骤:
第一步是分配ODBC环境,使一些内部结构初始化。完成这一步,须分配一个SQLHENV类型的变量在ODBC环境中做句柄使用。
第二步是为将要使用的每一个数据源分配一个连接句柄,由函数SQLALLocHandle()完成。
第三步是使用SQLConnect()把连接句柄与数据库连接,可以先通过SQLSetConnectAttr()设置连接属性。
然后就可以进行SQL语句的操作,限于篇幅,相关的函数就不具体介绍了,读者可以参考相关书籍。
操作完成后,用户取回相应的结果,就可以取消与数据库的连接。
最后需要释放ODBC环境。
ODBC API的特点是功能强大丰富,提供了异步操作,事务处理等高级功能,但相应的编程复杂,工作量大。
2.MFC ODBC类:MFC1.5后的版本里引入封装了ODBC功能的类。通过这些类提供与ODBC的接口,使得用户可以不须处理ODBC API中的繁杂处理就可以进行数据库操作。主要的MFC ODBC类如下。
CDatabase类:一个CDatabase对象表示一个到数据源的连接,通过它可以操作数据源。应用程序可使用多个CDatabase对象:构造一个对象并调用OpenEx()成员函数打开一个连接。接着构造CRecordSet对象以操作连接的数据源,并向CDatabase对象传递记录集构造程序指针。完成使用后用Close()成员函数销毁CDatabase对象。一般情况下并不需要直接使用CDatabase对象,因为CRecordSet对象可以实现大多数的功能。但是在进行事务处理时,CDatabase就起到关键作用。事务(Transaction)指的是将一系列对数据源的更新放在一起,同时提交或一个也不提交,为的是确保多用户对数据源同时操作时的数据正确性。
CRecordSet类:一个CRecordSet对象代表一个从数据源选择的一组记录的集合-记录集。记录集有两种形式:snapshot和dynaset。前者表示数据的静态视图,后者表示记录集与其他用户对数据库的更新保持同步。通过CRecordSet对象,用户可以对数据库中的记录进行各种操作。
CRecordView类:CRecordView对象是在空间中显示数据库记录的视图。这种视图是一种直接连到一个CRecordSet对象的格式视图,它从一个对话框模板资源创建,并将CRecordSet对象的字段显示在对话框模板的控件里。对象利用DDX和RFX机制,使格式上的控件和记录集的字段之间数据移动自动化,也就是说,用户甚至不要编写一行代码就可以实现简单的数据库记录查看程序。
CDBException类:由Cexception类派生,以三个继承的成员变量反映对数据库操作时的异常:
m_nRetCode:以ODBC返回代码(SQL_RETURN)的形式表明造成异常的原因。
m_strError:字符串,描述造成抛出异常的错误原因。
m_strStateNativeOrigin:字符串,用以描述以ODBC错误代码表示的异常错误。
MFC数据库类成员函数都能抛出CDBException类型的异常,所以在代码对数据库进行操作后监测异常是正确做法。
MFC ODBC类在实际开发中应用最广,因为它功能丰富,操作相对简便。 3.MFC DAO(数据访问对象)编程:DAO用于和微软的Access数据库接口。在数据库应用程序如果只需与Access数据库接口时,使用DAO编程较方便。其主要类如下。
CDaoWorkspace:CDaoWorkspace对象可以让一个用户管理从登陆到离开期间,指定的密码保护的数据库会话全过程。大多数情况下不要多个工作区也不要创建明确的工作区对象。因为在打开数据库和记录集对象时,它们可以使用DAO缺省工作区。
CDaoDatabase:代表一个连接,类似上述CDatabase类。
CDaoRecordSet:用来选择记录集并操作,类似上述CRecordSet类。
CDaoRecordView:类似上述CRecordView类。
CDaoException:类似上述CDBException类。
CDaoTableDef:表示基本表或附加表的定义。每个DAO数据库对象包括一个称为TableDef的收集,包含所有存储的DAO表定义对象。CDaoTableDef对象可以用来控制表定义。
CDaoQueryDef:CDaoQueryDef对象表示了一个查询定义(querydef)。
CDaoFieldExchange:支持数据库类使用的DAO字段交换(DFX)例程。也可处理事务,类似MFC ODBC类。
MFC DAO仅用来支持Access数据库,应用范围相对固定。 4.OLE DB:OLE DB在数据提供程序和用户之间提供了灵活的组件对象模型(COM)接口,这种灵活性有时会使得操作复杂化。OLE DB框架定义了应用的三个基本类。
数据提供程序Data Provider:拥有自己的数据并以表格形式显示数据的应用程序。提供OLE DB的行集COM接口,期显示范围可以从单一数据表格的简单提供者知道更复杂的分布式数据库系统。
使用者Consumers:使用OLE DB接口对存储在数据提供程序中的数据进行控制的应用程序。用户应用程序归为使用类。
服务提供程序Service Provider:是数据提供程序和使用者的组合。服务提供程序没有自己的数据,但使用
OLE DB使用者接口来访问存储在数据提供程序中的数据。然后,服务提供程序通过打开数据提供程序接口使得数据对使用者有效。服务提供程序常用于向应用程序提供高层次服务,比如高级分布式查询。
OLE DB编程时,用户使用组件对象开发应用程序。这些组件有:
枚举器:用于列出可用的数据源;
数据源:代表单独的数据和服务提供程序,用于创建对话;
对话:用于创建事务和命令;
事务:用于将多个操作归并为单一事务处理;
命令:用于向数据源发送文本命令(SQL),返回行集;
错误:用于获得错误信息。
5.ActiveX数据对象(ADO):是微软提供的面向对象的接口,与OLE DB类似,但接口更简单,具有更广泛的特征数组和更高程度的灵活性。ADO基于COM,提供编程语言可利用的对象,除了面向VC++,还提供面向其他各种开发工具的应用,如VB,VJ等。ADO在服务器应用方面非常有用,特别是对于动态服务器页面ASP(Active Server Page)。
ADO对象结构类似于OLE DB,但并不依靠对象层次。大多数情况下,用户只需要创建并只使用需要处理的对象。下面的对象类组成了ADO接口。
Connection:用于表示与数据库的连接,以及处理一些命令和事务。
Command:用于处理传送给数据源的命令。
Recordset:用于处理数据的表格集,包括获取和修改数据。
Field:用于表示记录集中的列信息,包括列值和其他信息。
Parameter:用于对传送给数据源的命令之间来回传送数据。
Property:用与操作在ADO中使用的其他对象的详细属性。
Error:用于获得可能发生的错误的详细信息。
在VC++使用ADO需要进行COM操作,详细方法在此就不赘述了。
在当今流行的分布式开发环境下,VC++6.0在数据库开发方面有较强的优势,学会
在不同的场合选用不同的技术,对开发人员来说是必要的技术。
http://www.vckbase.com/document/viewdoc.asp?id=215使用ADO实现BLOB数据的存取 -- ADO开发实践之二
http://www.vckbase.com/document/viewdoc.asp?id=252
http://www.vckbase.com/document/viewdoc.asp?id=496用MFC + ADO 把jpg图象文件放入ACCESS库中
http://www.vckbase.com/vckbase/vckbase23/
这些都是关系型数据库。比access先进得多。access是基于文件的。我个人觉得从用户角度讲sql server和oracle差不多,只是在查询性能上存在差异。由于sql语句定义是语义上的。所以各个公司自己在算法实施上有很大差异。一般的说来,oracle的要好于sql server。但是如果只有有限的几个表,几万行记录,这种差别是体现不出来的。但是oracle在建库和维护上要比sql server麻烦的多。至于sybase,他和sql server 基本一样。因为早期的sql server版本就是微软联合sybase开发的(6.6以前)。著名的数据库还有IBM DB2
http://www.xhstudio.net/show.asp?id=2185
在VC中动态加载ODBC的方法
方法一:修改注册表
设计思路
一般情况下,当用户在控制面板中配置好 ODBC数据源后, Windows系统便在注册表中加入了一些子键来存储用户的配置结果。当应用程序需要用到数据源时, Windows便会通知底层接口查阅注册表中该数据源的配置。如果用户删除了某个 ODBC数据源,那么也会在注册表中有所反应。如果配置的数据源是用户数据源, Windows系统便会修改注册表的 HKEY_CURRENT_USER\SOFTWARE\ODBC\ODBC.INI子键;如果配置的数据源是系统数据源, Windows系统便会修改注册表的 HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI主键。因此,我们可以在应用程序中使用 Windows API中的注册表编辑函数来完成 Windows所做的工作,这样就可以达到动态加载数据源的目的。
具体实现
对于不同类型的数据源,注册表的修改也各有不同,但基本上都要修改两个地方。一个是在 ODBC.INI子键下建立一个与数据源描述名同名的子键,并在该子键下建立与数据源配置相关的项;另一个是在 \ODBC.INI\ODBC Data Sources子键下建立一个新项以便告诉驱动程序管理器 ODBC数据源的类型。下面以配置一个 Microsoft Access数据源为例给出实现此功能的函数的代码。
/* strSourceName是要创建的数据源名, strSourceDb是数据库存放路径, strDescription是数据源的描述字符串。* /
BOOL CLoadOdbcDlg:: LoadDbSource(CString strSourceName,CString strSourceDb, CString strDescription)
{
//存放打开的注册表键
HKEY hKey;
DWORD dw;
//存放注册表 API函数执行的返回值
LONG lReturn;
//存放要打开的子键
CString strSubKey;
//检测是否安装了 MS Access ODBC driver:odbcjt32.dll
//获得 Windows系统目录
char sysDir[MAX_PATH];
char drvName[]=" \\odbcjt32.dll" ;
::GetSystemDirectory (sysDir,MAX_PATH);
strcat(sysDir,drvName);
CFileFind findFile;
if(!findFile.FindFile (sysDir))
{
AfxMessageBox("您的计算机系统中没有安装 MS Access的 ODBC驱动程序 odbcjt32.dll,您将无法加载该类数据源。 " ,MB_OK ¦MB_ICONSTOP);
return false;
}
strSubKey=" SOFTWARE\\ODBC\\ODBC.INI\\"+ strSourceName;
//创建 ODBC数据源在注册表中的子键
lReturn=::RegCreateKeyEx(HKEY_LOCAL_
MACHINE,(LPCTSTR)strSubKey,0,NULL,REG_OPTION
_NON_VOLATILE,KEY_WRITE,NULL,& hKey,& dw);
if(lReturn != ERROR_SUCCESS)
return false;
//设置数据源的各项参数
CString strDbq=strSourceDb;
CString strDriver=sysDir;
DWORD dwDriverId=25;
CString strFil=" MS Access" ;
CString strPwd=strSourceName;
DWORD dwSafeTransactions=0;
CString strUid=strSourceName;
::RegSetValueEx (hKey," DBQ" ,0L,REG_SZ,
(CONST BYTE* )((LPCTSTR) strDbq),strDbq .GetLength ()) ; ::RegSetValueEx (hKey," Description" ,0L,REG_SZ,(CONST BYTE* )((LPCTSTR)strDescription),strDescription.GetLength());
::RegSetValueEx (hKey," Driver" ,0L,REG_SZ,(CONST BYTE* )((LPCTSTR)strDriver),strDriver .GetLength ());
::RegSetValueEx (hKey," DriverId" ,0L,REG_DWORD,(CONST BYTE* )(& dwDriverId),sizeof(dw));
::RegSetValueEx (hKey," FIL" ,0L,REG_SZ,
(CONST BYTE* )((LPCTSTR) strFil),strFil .GetLength ());
::RegSetValueEx (hKey," PWD" ,0L,REG_SZ,
(CONST BYTE* )((LPCTSTR)strPwd),strPwd.GetLength ()) ; ::RegSetValueEx (hKey," SafeTransactions" ,0L,
REG_DWORD,(CONST BYTE* )(& dwSafeTransactions),sizeof(dw));
::RegSetValueEx (hKey," UID" ,0L,REG_SZ,
(CONST BYTE* )((LPCTSTR)strUid),strUid .GetLength ()); ::RegCloseKey(hKey);
//创建 ODBC数据源的 Jet子键
strSubKey+ =" \\Engines\\Jet" ;
lReturn=::RegCreateKeyEx (HKEY_LOCAL_MACHINE ,(LPCTSTR)strSubKey,0,NULL,REG_OPTION_NON_
VOLATILE,KEY_WRITE,NULL,& hKey,& dw);
if(lReturn != ERROR_SUCCESS)
return false;
//设置该子键下的各项参数
CString strImplict=" " ;
CString strUserCommit=" Yes" ;
DWORD dwPageTimeout=5;
DWORD dwThreads=3;
DWORD dwMaxBufferSize=2048;
::RegSetValueEx (hKey," ImplictCommitSync" ,0L,REG_SZ,(CONST BYTE* )((LPCTSTR)strImplict),strImplict.GetLength ()+ 1);
::RegSetValueEx (hKey," MaxBufferSize" ,0L,REG_DWORD,(CONST BYTE* )(& dwMaxBufferSize),sizeof(dw));
::RegSetValueEx (hKey," PageTimeout" ,0L,REG_DWORD,(CONST BYTE* )(& dwPageTimeout),sizeof(dw));
::RegSetValueEx (hKey," Threads" ,0L,REG_DWORD,(CONST BYTE* )(& dwThreads),sizeof(dw));
::RegSetValueEx (hKey," UserCommitSync" ,0L,REG_SZ,(CONST BYTE* )((LPCTSTR)strUserCommit),strUserCommit.GetLength ());
::RegCloseKey (hKey);
//设置 ODBC数据库引擎名称
lReturn=::RegOpenKeyEx (HKEY_LOCAL_MACHINE, " SOFTWARE\\ODBC\\ODBC.INI\\ODBC Data Sources" ,0L,KEY_WRITE,& hKey);
if(lReturn !=ERROR_SUCCESS)
return false;
CString strDbType=" Microsoft Access Driver (* .mdb)" ; ::RegSetValueEx (hKey,strSourceName,0L,REG_SZ,(CONST BYTE* )((LCTSTR)strDbType),strDbType.GetLength ());
return true;
}
由于在动态加载中,一般只会改变数据库文件、数据源说明以及数据源描述,故上述函数可以实现应用中的大部分要求。如果应用中还需要作更多的改变,那么也可以通过改变函数参数的方式加以实现。对于需要动态加载多种类型数据源的情况,可以用具有不同参数的重载函数去实现。
方法二:利用 DLL
设计思路
Windows系统子目录中的动态链接库 Odbcinst.dll提供了一个可以动态地增加、修改和删除数据源的函数 SQLConfigDataSource()。该函数的原型如下:
BOOL SQLConfigDataSource(HWND hwndParent,WORD fRequest, LPCSTR lpszDriver, LPCSTR lpszAttributes);
hwndParent参数是父窗口句柄。如果该值为 NULL,将不会显示与父窗口有关的对话框。
fRequest参数可以设置为下面的数值之一:
ODBC_ADD_DSN:增加一个新的用户数据源;
ODBC_CONFIG_DSN:修改(配置)一个已经存在的用户数据源;
ODBC_REMOVE_DSN:删除一个已经存在的用户数据源;
ODBC_ADD_SYS_DSN:增加一个新的系统数据源;
ODBC_CONFIG_SYS_DSN:修改 (配置 )一个已经存在的系统数据源;
ODBC_REMOVE_SYS_DSN:删除一个已经存在的系统数据源。
lpszDriver参数用于传递数据库引擎的名字,等同于方法一中 strDbType变量。
lpszAttirbutes参数是关键字的值,即一连串的 " keyname=value"字符串,每两个字符串之间用 " \"隔开,如 DSN=Personnel Data\0UID=Smith\0DATABASE=Personnel。关于该参数的详细设置请参阅 MSDN中 SQLConfigDataSource()函数的帮助文档和各种 ODBC驱动程序文档。
具体实现
由于 VC的缺省库文件中不包含 SQLConfigDataSource()函数,因此使用该函数之前需要将 odbcinst.h文件包含在工程的头文件中,在工程的 Settings属性对话框 Link属性页的 Object/library modules编辑框中增加 odbc32.lib,同时保证系统目录 system32下有文件 odbccp32.dll。
仍以 Microsoft Access为例,设置数据源名为 demo,数据源描述为 "示例数据源 ",那么在需要动态加载数据源的地方加入下列代码即可:
::SQLConfigDataSource (NULL,ODBC_ADD_SYS_DSN," Microsoft Access Driver (* .mdb)"," DSN=demo\0Descirption=示例数据库 " );
小结
上述两种方法都可以实现动态加载各种类型的 ODBC数据源,并且在 Windows95/98/NT/2000环境下调试通过。方法一在实现时需要较多的代码,方法二所需代码虽少,但需要额外文件的支持,而且随着数据源配置的灵活性的增加,为了形成 lpszAttributes字符串,其代码长度也会相应增加。由于从控制面板配置数据源使得程序员可以获得更加直观的理解,所以对于注册表中各项值以及相应项名称的获得除了可以查阅相关驱动程序的文档外,程序员也可以在编程前先通过控制面板配置 ODBC数据源,然后根据注册表中相应部分的内容进行编程
---------------------------
回复人: zhangshengyu(zhangshengyu)
做成服务是可以的,和应用程序一样,但是创建时必须要在参数dwServiceType中加入SERVICE_INTERACTIVE_PROCESS
-----------------------------
回复人: sjzxyg(小小鸟)
服务不能使用用户数据源,要使用系统数据源==============================这里当个FAQ,^_^
#import "C:\\Program Files\\Common Files\\System\\Ole DB\\oledb32.dll" no_namespace
_ConnectionPtr m_pConn;
......
IDataSourceLocatorPtr Locator;
Locator.CreateInstance(__uuidof(DataLinks));
::SetParent((HWND)(Locator->hWnd),this->GetSafeHwnd()); Locator->hWnd=(long)(::AfxGetMainWnd()->m_hWnd);
m_pConn=Locator->PromptNew();
CString str;
str=(char*)(m_pConn->ConnectionString);
m_pConn->Open(_bstr_t(str),"","",adConnectUnspecified); Locator.Release();
Locator = NULL;