一个好用的ODBC数据库类CMYODBC
?一個好用的ODBC數(shù)據(jù)庫類CMYODBC一、引言 感覺MFC的CRecordset類不是很好用,因為我們要想使用的話必須為每個查詢從CRecordset類派生出一個新類,或者進行動態(tài)數(shù)據(jù)交換。在VC知識庫第六期上面有一篇介紹"單獨使用CRecordset"文章,可是上面的CRecordset打開方式只能使用CRecordset::forwardOnly,游標只能向前滾動,而且用這種方式,你根本無法從打開的記錄集中獲得本次查詢得到了有多少列。有一次在應用的時候,我只好通過捕獲CRecordset::GetFieldValue()的異常來得到查詢的結果有多少列。為了使用的方便,我自己寫了一個數(shù)據(jù)庫類CMYODBC,它是用ODBC API寫的,它支持各種sql語句,支持事務處理。它最好的地方在于,對于查詢的記錄集實現(xiàn)了動態(tài)綁定,這是通過類CODBCSet來實現(xiàn)的。要說明的是,這兩個類可以說比較簡單,兩個類的代碼量很少,所以建議感興趣的朋友看一下它的代碼,下圖是本代碼運行效果圖: ? 二、原理 其實無論是使用ODBC API還是使用ORACLE的OCI(對于ORACLE的OCI感興趣的朋友,歡迎一起探討,OCI的功能很強大,支持動態(tài)綁定,支持pl/sql,它的類的封裝和CMYODBC很相似,用它來代替ODBC編程,可以解決ODBC的效率問題)其過程都很相似,一般分為以下幾個過程: ????? 1 初始化工作環(huán)境 ????? 2 連接數(shù)據(jù)源 ????? 3 操作數(shù)據(jù)源 ????? 4 檢索結果集 ????? 5 更新結果集 ????? 6 事務處理 ????? 7 斷開連接,釋放各種句柄 大家都知道在使用CDatabase時候,如果要執(zhí)行的是select語句的話,那么要通過CRecordset來檢索結果集,而CRecordset類要我們先選擇表等來先進行綁定,這樣我們使用的時候很不方便,其實我們根本不需要這樣做,而且我們也不需要知道這次執(zhí)行的是關于那個數(shù)據(jù)庫那張表的sql語句,因為在執(zhí)行完SQLExecDirect()后,可以通過調用SQLNumResultCols() 、SQLColAttribute()等函數(shù)來獲得執(zhí)行的結果的很多屬性,如這次執(zhí)行的結果集是多少列、每列的字段名、列的類型等,然后根據(jù)類型可以動態(tài)分配內存,然后在用這些內存去綁定,最后能過SQLFetch()來得到結果集。在CMYODBC這個類里是通過CODBCSet類應用上面的原理來實現(xiàn)自動綁定的。 下面介紹一下類CMYODBC的使用方法: 源代碼下載 1 通過調用ConnectDB(const char *cpServerName, const char *cpUserName, const char *cpPassword)函數(shù)來聯(lián)接數(shù)據(jù)庫。其中的參數(shù)意義如下: ????? cpServerName-----ODBC數(shù)據(jù)源名 ????? cpUserName-------用戶名 ????? cpPassword-----口令 2 通過調用ExeSqlDirect(const char *cpSqlStmt)函數(shù)可以執(zhí)行一些操作數(shù)據(jù)源的語句,如修改、刪除語句等。其中的參數(shù)意義如下: cpSqlStmt------你要執(zhí)行的sql語句,如delete from emp where deptno < 20? 3 如果要執(zhí)行事務的話,調用ExecTrans(CStringList &strSqlList)函數(shù),其中的參數(shù) strSqlList表示你要執(zhí)行的一系列sql語句。 4 如果要執(zhí)行select語句的話,通過下面的步驟: ????? I 聲明一個CODBCSet 對象,如 CODBCSet rSet; ????? II然后調用函數(shù)PrepareSql(const char *cpSql, CODBCSet &rset),其中的參數(shù)的意義如下: ????????? cpSql----代表要執(zhí)行的select語句 ????????? rset-----表示一個CODBCSet的引用,你要把上面聲明的對象傳遞進去。 ????? III調用FetchData()函數(shù)來取得結果集。 5 通過調用函數(shù)DisConnect()斷開和數(shù)據(jù)源的連接。 三、實例練習 下面就通過上面的例子一起來看一下這個類到底怎么樣,為了方便,我建了一個簡單的access數(shù)據(jù)庫test.mdb,在這個數(shù)據(jù)庫中也只有一張表emp,它有三個字段。在下面的工程的InitInstance ()中,通過代碼為它自動建立了一個叫做"daliu"的ODBC數(shù)據(jù)源。 步驟一: 新建一個基于對話框的工程,命名為demo1,打開stdafx.h文件,加入#include 從例子中把MyODBC.h,MyODBC.cpp, ODBCSet.h, ODBCSet.cpp復制到這個工程的目錄下,并且加入到工程中,方法是菜單project->add to project->files,選擇這四個文件就可以了。復制test.mdb文件,把它加入到這個工程的debug目錄下。也可以是其它的目錄,只要和你的執(zhí)行程序在同一個目錄就可以了。 步驟二: 參照上面的對話框,在上面加入按鈕和一個ClistCtrl控件,在classwizard上面關聯(lián)控件的變量ClistCtrl關聯(lián)m_list控件,為三個EDIT分別關聯(lián)CString類型的m_strID,m_strName,m_strJob. 步驟三: 在CDemo1App::InitInstance()的最上面,加入下面的代碼,實現(xiàn)自動ODBC數(shù)據(jù)源的增加。 01.char?path[MAX_PATH] = {''\0''}; 02.GetModuleFileName(NULL,path,MAX_PATH);//得到執(zhí)行文件名 03.m_strExePath.Format("%s", path); 04.int?iPosition; 05.iPosition = m_strExePath.ReverseFind(''\\''); 06.m_strExePath = m_strExePath.Left(iPosition + 1); 07.CString strAccessPath = m_strExePath +?"test.mdb";//得到這個數(shù)據(jù)庫文件的路徑 08.int?iLen = strAccessPath.GetLength(); 09.char?cpConfig[MAX_PATH]; 10.//由于在這個聯(lián)結串中有靠\0來分開數(shù)據(jù)源每個配置信息項的,所以只好用下面的笨方法了。 11.strcpy(cpConfig,?"DSN=daliu\0"); 12.strcpy(cpConfig + 10,?"DBQ="); 13.strcpy(cpConfig + 14, strAccessPath); 14.strcpy(cpConfig + 14 + iLen,?"\0"); 15.strcpy(cpConfig + 15 + iLen,?"DEFAULTDIR="); 16.strcpy(cpConfig + 15 + iLen + 11, m_strExePath); 17.strcpy(cpConfig + 25 + iLen + m_strExePath.GetLength(),?"\0\0"); 18.? 19.if(!SQLConfigDataSource(NULL,ODBC_ADD_SYS_DSN, 20."Microsoft Access Driver (*.mdb)\0",cpConfig))//設置odbc數(shù)據(jù)源步驟四: 設置Clistctrl控件的風格,為他加入圖象資源。 首先要在CDemo1Dlg中加入#include"ODBCSet.h"#include"MyODBC.h",然后在CDemo1Dlg中添加成員變量CimageList ImageList;添加成員函數(shù)BOOL ShowData() 在CDemo1Dlg::OnInitDialog()中加入下面的代碼: 01.ImageList.Create(16,16,ILC_COLOR8,0,5); 02.ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON1)); 03.DWORD?dwStyle=GetWindowLong(m_list.GetSafeHwnd(),GWL_STYLE); 04.dwStyle |= LVS_REPORT; 05.SetWindowLongA(m_list.GetSafeHwnd(),GWL_STYLE,dwStyle); 06.m_list.SetExtendedStyle(LVS_EX_HEADERDRAGDROP|LVS_EX_FULLROWSELECT|LVS_EX_TRACKSELECT); 07.m_list.SetImageList(&ImageList, LVSIL_SMALL); 08.? 09.ShowData()//這個函數(shù)是用來向列表框中插入數(shù)據(jù)的。下面我們來分析一下ShowData()函數(shù),它是使用CMYODBC的關鍵。 01.BOOL?CDemo1Dlg::ShowData() 02.{ 03.int?i = 0, iCount; 04.m_list.DeleteAllItems(); 05.//首先清空listview 06.iCount = m_list.GetHeaderCtrl()->GetItemCount(); 07.for(i = 0; i < iCount; i++) 08.{ 09.m_list.DeleteColumn(0); 10.} 11.for(i = 0; i < iCount; i++) 12.{ 13.m_list.GetHeaderCtrl()->DeleteItem(0); 14.} 15./*上面的代碼用于清空ClistCtrl控件中項,上面的兩個循環(huán)并不能合成一個,你可以試一下*/ 16.CString strSql; 17.strSql =?"select * from emp"; 18.//sql查詢語句 19.CMyODBC db; 20.//聲明CMyODBC類的實例 21.CODBCSet set; 22.//聲明CODBCSet類的實例 23./*聯(lián)接數(shù)據(jù)庫,由于access數(shù)據(jù)庫沒有設定用戶和口//令,所以它們兩個就用空的字符串代替*/ 24.db.ConnectDB("daliu","",?""); 25./*準備sql語句,你可以跟蹤一下,在這個函數(shù)中完成動態(tài)的綁定,得到共有幾列,每列的名稱等*/ 26.db.PrepareSql(strSql, set); 27.? 28.for(i = 0; i < set.GetCols(); i++) 29./*set.GetCols()得到本次查詢得到了幾列。*/ 30.{ 31.m_list.InsertColumn(i, set.m_coldatafmt[i].name,LVCFMT_CENTER,80); 32.} 33./*上面的循環(huán)用于插入列, m_coldatafmt是一個COL_DATAFMT_ODBC的結構, 34.在我們調用db.PrepareSql()后,它就含有了每個列的名稱,字段數(shù)據(jù)類型,字段數(shù)據(jù)長度信息。*/ 35.? 36./*下面的循環(huán)用于向列表框中插入數(shù)據(jù), set.m_coldata是一個COL_DATA_ODBC的結構, 37.當含有當前行的數(shù)據(jù)值,數(shù)據(jù)值的長度信息,這樣就實現(xiàn)了從記錄集中取數(shù)據(jù)的功能。*/ 38.int?iRow = 0; 39.while(db.FetchData()) 40./*每次取回一條記錄。*/ 41.{ 42.for(i = 0; i < set.GetCols(); i++) 43.{ 44.if(i == 0) 45.{ 46.m_list.InsertItem(iRow, set.m_coldata[0].value); 47.} 48.else 49.{ 50.m_list.SetItemText(iRow, i, set.m_coldata[i].value); 51.} 52.} 53.iRow++; 54.} 55.set.Empty(); 56./*清空記錄集*/ 57.db.DisConnect(); 58./*斷開連接*/ 59.return?TRUE;??? 60.}下面我們再來看一個如何插入一條記錄: 01.void?CDemo1Dlg::OnBtnadd() 02.{ 03.UpdateData(TRUE); 04.CString strSql; 05.strSql.Format("insert into emp values(%d,''%s'',''%s'')",atoi(m_strID), m_strName, m_strJob); 06.CMyODBC db; 07.db.ConnectDB("daliu","",?""); 08.//連接數(shù)據(jù)庫 09.db.ExeSqlDirect(strSql); 10.//執(zhí)行sql語句 11.db.DisConnect(); 12.//斷開連接 13.this->ShowData(); 14.//刷新數(shù)據(jù) 15.}響應其它的按鈕的函數(shù)就不一一寫了,和上面的都差不多,希望通過它能給我們用VC的開發(fā)數(shù)據(jù)庫工程帶來一些方便。 四、總結 ODBC有很多用處,例如我們可以把很多信息按照一定的格式保存在文本中(因為在商業(yè)上用別人的數(shù)據(jù)庫都是要買的),然后通過ODBC把這些文本文件映射成表,這些文件的目錄就成為一個數(shù)據(jù)庫,這些我們就可以很方便的對這些文件的內容通過sql來操作查詢,這樣開發(fā)的效率會高一些,而且是在本地,速度完全可以滿足。 |
轉載于:https://www.cnblogs.com/Dageking/archive/2013/03/13/2957151.html
《新程序員》:云原生和全面數(shù)字化實踐50位技術專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的一个好用的ODBC数据库类CMYODBC的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android支持第三方jar包,以及E
- 下一篇: 使用RMAN VALIDATE验证数据和