2007-06-10
如何在c#中实现对数据库数据的修
这是C#对通过ODBC链接的数据库进行的操作。只需要在应用程序里面指定已经配置好的数据源就可以连接,访问数据库。但是,这种方式也有一定的局限性,需要手工的在ODBC数据源里面配置。需要教会程序的使用者如何去配置,而且,如果一不小心更改了ODBC数据源的配置(也许是无意的)。 就会造成连接数据库失败。这时候,程序的使用人员也许会一筹莫展,束手无策。自然的,读者就会提出这样一个问题,能不能不通过ODBC数据源的配置,而在程序里面,根据程序安装的环境,自动的配置数据库连接。 答案是肯定的,下面我们就介绍一种在程序中通过修改Window注册表的办法来动态的配置ODBC数据源的方法。其实现的基本...全部
这是C#对通过ODBC链接的数据库进行的操作。只需要在应用程序里面指定已经配置好的数据源就可以连接,访问数据库。但是,这种方式也有一定的局限性,需要手工的在ODBC数据源里面配置。需要教会程序的使用者如何去配置,而且,如果一不小心更改了ODBC数据源的配置(也许是无意的)。
就会造成连接数据库失败。这时候,程序的使用人员也许会一筹莫展,束手无策。自然的,读者就会提出这样一个问题,能不能不通过ODBC数据源的配置,而在程序里面,根据程序安装的环境,自动的配置数据库连接。
答案是肯定的,下面我们就介绍一种在程序中通过修改Window注册表的办法来动态的配置ODBC数据源的方法。其实现的基本思想是这样的:先把开发环境下的注册表中的ODBC数据源信息导出到一个文件中,然后将导出的内容作为应用程序中的字符串常量进行保存。
在程序运行的时候,检查ODBC数据源的注册情况,如果发现注册不正确,就根据环境的信息和字符串常量动态的确定注册表的内容,写如一个临时的注册表文件中。用批处理文件将该临时文件中的ODBC数据源信息导入到系统注册表,从而实现了ODBC数据源的动态注册。
操作步骤1。运行注册表编辑器程序(Regedit。exe)。2。从注册表项HKEY_CURRENT_USERSoftwareODBCODBC。INIODBCDataSources下导出数据源名称信息到Reg1。
reg文件中。这个表项下面存放的是用户定义的数据源,如果需要系统数据源信息,则可导出HKEY_Local_MachineSoftwareODBC。INIODBCDataSources到注册文件中。
3。导出要注册的数据源名称的具体连接参数信息到db2。reg中。在此,以导出名称为“PostMdb”的数据为例,具体路径:HKEY_CURRENT_USERSoftwareODBCODBC。INIPostMdb。
4。用文本编辑器如(NotePad。exe)打开上述db1。reg文件,保留数据源名称为PostMdb的行;并将db2。reg文件内容与当前db1。reg内容合并。假设修改后“PostMdb”数据源注册信息如下:REGEDIT4[HKEY_CURRENT_USERSoftwareODBCODBC。
INIODBCDataSources]″PostMdb″=″MicrosoftAccessDriver(*。mdb)″[HKEY_CURRENT_USERSoftwareODBCODBC。INIPostMdb]″Driver″=″C:\WINDOWS\SYSTEM\ODBCJT32。
DLL″″DBQ″=″c:\MyDocuments\db1。mdb?r>″Description″=″PostCardMisDatabase″″DriverId″=″FIL″=″MSAccess;″″SafeTransactions″=″UID″=″″[HKEY_CURRENT_USERSoftwareODBCODBC。
INIPostMdbEngines][HKEY_CURRENT_USERSoftwareODBCODBC。INIPostMdbEnginesJet]″ImplicitCommitSync″=″″″MaxBufferSize″=″PageTimeout″=″Threads″=″UserCommitSync″=″Yes″5。
动态注册ODBC数据源的实现从上述注册信息可以看出,对于特定的数据源来说,实际上要动态确定的只是“Driver”和“DBQ”两项内容。将“Driver”=“C:\WINDOWS\SYSTEM\ODBCJT32。
DLL”修改为“Driver”=“%s\ODBCJT32。DLL”,将“DBQ”=“c:\MyDocuments\db1。mdb”修改为“DBQ”=“%s\db1。mdb”。复制修改后的注册信息到程序单元中存储为一字符串常量,命名为OdbcStr。
以下以Delphi为例说明实现方法。为便于说明,假设主窗体名称为Form1,通过一命令钮Button1注册ODBC数据源。具体根据读者需要自行设定。procedureTForm1。Button1Click( ); :double; :PChar;AppPath,Params,Path, //生成注册用的批处理文件Params:=′Regedit/stmp。
reg′;//批处理文件内容AppPath:=ExtractFilePath(Application。ExeName);//取得应用程序当前路径AssignFile(RegF,AppPath+′Reg。
Bat′);//指定批处理文件路径和名称ReWrite(RegF);//创建和打开指定的文本文件WriteLn(RegF,Params);//将注册命令批处理内容写入文件CloseFile(RegF);//生成注册表文件GetMem(SysDir,255);GetSystemDirectory(SysDir,255);//取得Windows系统目录Path:=String(SysDir);Path:=InsertSplash(Path);//将类似C:WINDOWSSYSTEM变为C:\WINDOWS\SYSTEMDelete(AppPath,Length(AppPath),1);//将字符串尾部′′字符删除DbPath:=InsertSplash(AppPath);//取得数据库存放路径Params:=Format(OdbcStr,[Path,DbPath]);AssignFile(RegF,AppPath+′Tmp。
Reg′);ReWrite(RegF);WriteLn(RegF,Params);CloseFile(RegF);//通过Api函数执行reg。bat,Uses中加入对ShellApi的引用IfShellExeCute(Application。
Handle,′Open′,′Reg。bat′,′′,PChar(AppPath),SW_HIDE)$#@60;=32thenShowmessage(′导入注册表文件信息失败′);finallyFreeMem(SysDir);end;end;上述代码调用了一字符串处理函数InsertSplash,用于将路径字符串中所有的′′处理为′\′;这样做是必需的,否则,上述注册信息DRIVER和DBQ项无法正确注册。
InsertSplash函数代码如下:functionInsertSplash( ):string;//需要在单元公有部分进行函数声明 :=1toLength(AStr)docaseAStr[I]=′′ :=Result+′\′; :=Result+AStr[I];end;上述操作实现ODBC数据源的动态注册并没有通过Delphi特有的功能去完成,而只是通过文件读写功能,根据具体安装环境,生成ODBC数据源注册信息和批处理文件,以完成ODBC数据源的注册。
这种实现方法不依赖于某种特定的开发工具,不需要通过手工进行ODBC数据源的配置,具有通用性强和操作简单的特点。而且,用上述同样的方法,读者也可编写能够注册其它类型数据源的程序,甚至,写成ODBC注册动态连接库,以利于程序复用。
不管是是控制面版里面配置ODBC数据源,还是象上面上的通过修改注册表在程序中动态的配置ODBC数据源,都没有离开数据源这个基本概念。在设置好了数据源之后,就可以在应用程序中连接数据源,然后对数据库中的数据进行数据的增加、删除和修改了。
对数据库中数据的访问,总的来说有两种方法,一种是通过编程环境提供的控件方法,一种就是通过ODBCAPI。有人也许会说还可以通过BDE的API,其实BDE的API和ODBC的API是同样的一个概念,BDE的API是Borland公司的,只是在他的编译环境下使用,当然,Borland的编译环境下比ODBC还快,但是因为那是他自带的驱动程序,如果数据库要升级的话,原来的BDE中的驱动程序就可能不能用了,所以,我们还是提倡使用ODBC的方法。
ODBCAPI函数中通过设置参数,直接和数据库打交道,这样的效率比较高,但是编程变的复杂,而且一不小心就会出错。我们不提倡直接使用ODBCAPI,而倾向于使用编程环境提供的控件方法来访问。但是,作为一种访问数据库访问的方法,我们在这里还是做一简单的介绍(这里以VB为例子)。
(至于通过控件的方法,大家使用的比较多,这里就不多说了。)ODBCAPI函数的声明方法与使用其它动态库函数一样,在VB中使用ODBCAPI函数之前,必须事先声明将要使用的函数、常量和数据结构。
ODBCAPI函数驻留在ODBC运行动态库ODBC。DLL(16位)或ODBC32。DLL(32位)中,该动态库位于Windows子目录system中。通常做法是在VB项目中单独使用一个模块文件,然后将ODBCAPI声明语句加入其中。
下面就是本文实例中使用的模块文件module1。bas的内容。DeclareFunctionSQLAllocEnvLib"odbc32。dll"(phenv&)AsIntegerDeclareFunctionSQLAllocConnectLib"odbc32。
dll"(ByValhenv&,phdbc&)AsIntegerDeclareFunctionSQLAllocStmtLib"odbc32。dll"(ByValhdbc&,phstmt&)AsIntegerDeclareFunctionSQLConnectLib"odbc32。
dll"(ByValhdbc&,ByValszDSN$,ByValcbDSN%,ByValszUID$,ByValcbUID%,ByValszAuthStr$,ByValcbAuthStr%)AsIntegerDeclareFunctionSQLColAttributesStringLib"odbc32。
dll"Alias"SQLColAttributes"(ByValhstmt&,ByValicol%,ByValfDescType%,ByValrgbDescAsString,ByValcbDescMax%,pcbDesc%,pfDesc&)AsIntegerDeclareFunctionSQLDisconnectLib"odbc32。
dll"(ByValhdbc&)AsIntegerDeclareFunctionSQLExecDirectLib"odbc32。dll"(ByValhstmt&,ByValszSqlStr$,ByValcbSqlStr&)AsIntegerDeclareFunctionSQLFetchLib"odbc32。
dll"(ByValhstmt&)AsIntegerDeclareFunctionSQLFreeConnectLib"odbc32。dll"(ByValhdbc&)AsIntegerDeclareFunctionSQLFreeEnvLib"odbc32。
dll"(ByValhenv&)AsIntegerDeclareFunctionSQLFreeStmtLib"odbc32。dll"(ByValhstmt&,ByValfOption%)AsIntegerDeclareFunctionSQLGetDataLib"odbc32。
dll"(ByValhstmt&,ByValicol%,ByValfCType%,ByValrgbValueAsString,ByValcbValueMax&,pcbValue&)AsIntegerDeclareFunctionSQLNumResultColsLib"odbc32。
dll"(ByValhstmt&,pccol%)AsIntegerGlobalConstSQL_C_CHARAsLong=1GlobalConstSQL_COLUMN_LABELAsLong=18GlobalConstSQL_DROPAsLong=1GlobalConstSQL_ERRORAsLong=-1GlobalConstSQL_NO_DATA_FOUNDAsLong=100GlobalConstSQL_SUCCESSAsLong=0(更多的ODBCAPI,可以在MSDN里面查到)另外,在VB子目录samplesemautodb_odbc中有两个文本文件ODBC16。
TXT和ODBC32。TXT,分别存有所有16位和32位ODBCAPI函数、常量和数据结构的声明语句,编程时可以从中拷贝所需的声明语句。使用ODBCAPI编程方法分为如下一些步骤:1、初始化ODBC在这个过程中,应用程序将通过调用SQLAlloEnv函数初始化ODBC接口,获取ODBC环境句柄。
ODBC环境句柄是其它所有ODBC资源句柄的父句柄,因此无论程序将建立多少个ODBC连接,这个过程只需执行一次即可。例如:DimrcAsInteger"ODBC函数的返回码DimhenvAsLong"ODBC环境句柄rc=SQLAllocEnv(henv)"获取ODBC环境句柄2、与ODBC数据源建立连接这个过程由下列两个步骤组成:a、调用SQLAllocConnect函数获取连接句柄。
例如:DimhdbcAsLong"连接句柄rc=SQLAllocConnect(henv,hdbc)"获取连接句柄B、建立连接。这个步骤可以通过多种方法实现,最简单直观的方法是调用SQLConnect函数。
例如:DimDSNAsString,UIDAsString,PWDAsStringDSN="DataSourceName""ODBC数据源名称UID="UserID""用户帐号PWD="Password""用户口令rc=SQLConnect(hdbc,DSN,Len(DSN),UID,Len(UID),PWD,Len(PWD))"建立连接3、存取数据用户对ODBC数据源的存取操作,都是通过SQL语句实现的。
在这个过程中,应用程序将通过连接向ODBC数据库提交SQL语句,完成用户请求的操作,具体步骤如下:调用SQLAllocStmt函数获取语句句柄,例如DimhstmtAsLongrc=SQLAllocStmt(hdbc,hstmt)执行SQL语句。
执行SQL语句的方法比较多,最简单明了的方法是调用SQLAllocStmt函数,例如:DimSQLstmtAsStringSQLstmt="SELECT*FROMauthors"rc=SQLExecDirect(hstmt,SQLstmt,Len(SQLstmt))4、检索结果集如果SQL语句顺利提交并正确执行,那么就会产生一个结果集。
检索结果集的方法很多,最简单、最直接的方法是调用SQLFetch和SQLGetData函数。SQLFetch函数的功能是将结果集的当前记录指针移至下一个记录,SQLGetData函数的功能是提取结果集中当前记录的某个字段值。
通常可以采用一个循环提取结果集中所有记录的所有字段值,该循环重复执行SQLFetch和SQLGetData函数,直至SQLFetch函数返回SQL_NO_DATA_FOUND,这表示已经到达结果集的末尾。
DimColValAsString*225ColVal=String(255,0)DoUntilSQLFetch(hstmt)=SQL_NO_DATA_FOUNDrc=SQLGetData(hstmt,i,SQL_C_CHAR,ColVal,Len(ColVal),SQL_NULL_DATALoop5、结束应用程序在应用程序完成数据库操作、退出运行之前,必须释放程序中使用的系统资源。
这些系统资源包括:语句句柄、连接句柄和ODBC环境句柄。完成这个过程的步骤如下:调用SQLFreeStmt函数释放语句句柄及其相关的系统资源。
例如:rc=SQLFreeStmt(hstmt,SQL_DROP)调用SQLDisconnect函数关闭连接,例如:rc=SQLDisconnect(hdbc)调用SQLFreeConnect函数释放连接句柄及其相关的系统资源,例如:rc=SQLFreeConnect(hdbc)调用SQLFreeEnv函数释放环境句柄及其相关的系统资源,停止ODBC操作,例如:rc=SQLFreeEnv(henv)。收起