胡兆峰,史高揚(yáng)
(西安電子科技大學(xué)電子信息攻防對(duì)抗與仿真重點(diǎn)實(shí)驗(yàn)室,陜西西安 710071)
在編程過程中,數(shù)據(jù)庫毫無疑問是一個(gè)不可忽視的部分,數(shù)據(jù)庫可以完成對(duì)數(shù)據(jù)的存儲(chǔ)和檢索,可以方便人們的工作,提高工作效率。然而,因?yàn)榍度胧街悄茉O(shè)備的資源有限,對(duì)數(shù)據(jù)庫的使用有較大限制。在Windows CE操作系統(tǒng)中,提供了一套自帶的數(shù)據(jù)庫。該數(shù)據(jù)庫具有數(shù)據(jù)結(jié)構(gòu)簡(jiǎn)單,操作靈活等特性,在存儲(chǔ)數(shù)量較小的情況下可以方便使用[1]。
Windows CE操作系統(tǒng)專門供掌上電腦和嵌入式設(shè)備使用的系統(tǒng)環(huán)境。Windows CE被設(shè)計(jì)成針對(duì)小型設(shè)備的通用操作系統(tǒng)。與其它的微軟Windows操作系統(tǒng)不同,Windows CE并不代表一個(gè)采用相同標(biāo)準(zhǔn)對(duì)所有平臺(tái)都適用的軟件。為了足夠靈活以適應(yīng)廣泛產(chǎn)品,Windows CE可采用不同的標(biāo)準(zhǔn)模式,即它能從一系列軟件模式中做出選擇,從而使產(chǎn)品得到定制。通過選擇,Windows CE能達(dá)到系統(tǒng)要求的最小模式,從而減少存儲(chǔ)腳本和操作系統(tǒng)的運(yùn)行。
從Windows CE 5.0開始,Windows CE自帶數(shù)據(jù)庫系統(tǒng)就包括了 EDB和 CEDB,CEDB是 Windows CE 5.0之前就支持的數(shù)據(jù)庫系統(tǒng),EDB是 Windows CE5.0之后新增的數(shù)據(jù)庫系統(tǒng),EDB可以理解成對(duì)CEDB的升級(jí)。EDB是一個(gè)基于SQL Server CE的嵌入式數(shù)據(jù)庫引擎,為基于Windows CE的應(yīng)用程序提供核心功能,通過使用EDB,開發(fā)者能夠創(chuàng)建一個(gè)對(duì)象存儲(chǔ),成為數(shù)據(jù)庫卷,其中可以包含多個(gè)數(shù)據(jù)庫,該數(shù)據(jù)庫卷是基于文件的,因此可以被復(fù)制和移動(dòng)[2]。
在Windows CE系統(tǒng)中,學(xué)生信息存儲(chǔ)的數(shù)據(jù)都是以EDB形式存儲(chǔ)的。本文結(jié)合學(xué)生信息管理系統(tǒng)的實(shí)例介紹了EDB數(shù)據(jù)庫的設(shè)計(jì)與應(yīng)用開發(fā)。建立一個(gè)EDB數(shù)據(jù)庫的基本思路是:首先加載數(shù)據(jù)庫卷,然后在加載的數(shù)據(jù)庫卷中建立數(shù)據(jù)庫,數(shù)據(jù)庫建立好后再打開數(shù)據(jù)庫以對(duì)數(shù)據(jù)庫進(jìn)行讀寫等操作[3]。
建立數(shù)據(jù)庫之前應(yīng)加載數(shù)據(jù)庫卷,可以使用CeMountDBVol函數(shù)來實(shí)現(xiàn),其函數(shù)定義如下:
BOOL CeMountDBVolEx(PCEGUID pGuid,LPWSTR lpwszDBVol,CEVOLUMEOPTIONS*poptions,DWORD dwFlags);
參數(shù)pGuid用來標(biāo)識(shí)數(shù)據(jù)庫文件的GUID,參數(shù)lpwszDBVol表示裝備數(shù)據(jù)庫卷的文件名稱,參數(shù)poptions設(shè)置新數(shù)據(jù)庫卷的行為和性能。如果此數(shù)據(jù)庫卷已經(jīng)被建立,此參數(shù)將被忽略參數(shù)poptions值為NULL,系統(tǒng)將設(shè)置默認(rèn)的數(shù)據(jù)庫卷行為和性能,參數(shù)dwFlag表示數(shù)據(jù)庫卷被裝載的方式。
加載數(shù)據(jù)庫卷后,應(yīng)該穿件數(shù)據(jù)庫,此時(shí)可以用CeCreateDatabaseEx來創(chuàng)建數(shù)據(jù)庫,定義如下:
CEOID CeCreateDatabaseWithProps(PCEGUID pGuid,CEDBASEINFOEX*pInfo,
DWORD cProps,CEPROPSPEC*prgProps);
參數(shù)pGuid指向已裝配的數(shù)據(jù)庫卷標(biāo)識(shí),參數(shù)pInfo指向CEDBASEINFOEX結(jié)構(gòu)指針,用來藐視被創(chuàng)建的數(shù)據(jù)庫的名稱、類型、排序方式以及數(shù)據(jù)庫特征等信息。
在數(shù)據(jù)庫建立好之后,需要對(duì)數(shù)據(jù)庫進(jìn)行操作,如添加記錄,刪除記錄,修改記錄,查找記錄。實(shí)現(xiàn)以上操作的方法定義如下:
(1)讀取記錄。
CEOID CEReadRecordPropsEx(HANDLE hDatabase,DWORD dwFlags,LPWORD lpcPropID,CEPROPID*prgPropID,LPBYTE lplpbuffer,LPDWORD lpcbBuffer,HANDLE hHeap);
參數(shù)dwFlags為讀取標(biāo)識(shí),參數(shù)lpcPropID表示參數(shù)rgPropID指向CEPROPID結(jié)構(gòu)的數(shù)量。參數(shù)lplp-Buffer表示緩沖區(qū),用于存儲(chǔ)讀取到的記錄信息。
(2)寫記錄。
CEOID CeWriteRocordProps(HANDLE hDatabase,CEOID oidRecord,WORD cPropsID,CEPROPVAL*prg-PropVal);
參數(shù)oidRecord表示要寫入記錄的標(biāo)識(shí),如果參數(shù)是0,表示添加一條新紀(jì)錄,否則表示要更改記錄。參數(shù)cPropID表示要寫入記錄的字段個(gè)數(shù),參數(shù)prgProp-Val表示要寫入記錄的結(jié)構(gòu)體。
(3)刪除記錄。
BOOL CeDeleteRecord(HANDLE hDatabase,CEOID oidRecord);
參數(shù) hDatabase表示要?jiǎng)h除的數(shù)據(jù)庫句柄,oidRecord表示要?jiǎng)h除的記錄ID。
在對(duì)EDB進(jìn)行操作前需要先定義一個(gè)宏,即#define EDB,將其加載開發(fā)工程中的stdafx文件中,否則將無法使用EDB相關(guān)的函數(shù)。具體數(shù)據(jù)庫的創(chuàng)建思路與上文相同,本數(shù)據(jù)庫共由5個(gè)字段構(gòu)成,分別是學(xué)生姓名,學(xué)號(hào),性別,聯(lián)系電話,照片。
首先加載Windows CE系統(tǒng)學(xué)生信息數(shù)據(jù)庫所在的卷文件“\student.vol”,然后再打開數(shù)據(jù)庫,本數(shù)據(jù)庫有兩個(gè)排序字段,分別是姓名和學(xué)號(hào),這樣在搜索數(shù)據(jù)庫時(shí)可以利用EDB自帶的API函數(shù)對(duì)這兩個(gè)字段的類內(nèi)容進(jìn)行搜索。
通過對(duì)EDB數(shù)據(jù)庫進(jìn)行分析,可以得到各個(gè)屬性的PropID,從而對(duì)學(xué)生信息進(jìn)行讀取。核心代碼如下:
/* -------------------
【函數(shù)介紹】:讀取記錄;根據(jù)學(xué)生編號(hào),修改記錄
【入口參數(shù)】:strNo:學(xué)生編號(hào)
pRecStudent:學(xué)生數(shù)據(jù)庫表結(jié)構(gòu)
【出口參數(shù)】:(無)
【返回值】:TRUE:編輯成功;FALSE:編輯失敗
-------------------*/
ceOid=CeSeekDatabaseEx(tblStudent.m_hDB,CEDB_SEEK_VALUEFIRSTEQUAL,(DWORD)&seekPropVal,1,&dwIndex);
if(ceOid==0)
{TRACE(L"未查找到此記錄 ");
goto error;}
//寫入記錄
tmpCeOid=CeWriteRecordProps(tblStudent.m_hDB,ceOid,4,pProps);
if(tmpCeOid==0){
TRACE(L"寫入記錄失敗 ");
goto error;}
如果要從數(shù)據(jù)庫中刪除一個(gè)學(xué)生信息,只需要換的該學(xué)生信息的CEOID,然后通過調(diào)用CEDeleteRecord函數(shù)刪除。
ceOid=CeSeekDatabaseEx(tblStudent.m_hDB,CEDB_SEEK_VALUEFIRSTEQUAL,(DWORD)&seekPropVal,1,&dwIndex);
if(ceOid==0)
{TRACE(L"未查找到此記錄 ");
goto error;
}
//刪除當(dāng)前記錄
if(!CeDeleteRecord(tblStudent.m_hDB,ceOid))
{TRACE(L"刪除記錄失敗 ");
goto error;
}
向數(shù)據(jù)庫添加一個(gè)學(xué)生信息,需要先填充屬性結(jié)構(gòu)CEPROPVAL,然后調(diào)用 CEWriteRecordProps添加。該函數(shù)也可以用于修改某個(gè)已經(jīng)存在的記錄屬性值。
//首先填充CEPROPVAL屬性結(jié)構(gòu)
CEPROPVAL pProps[4];
DWORD dwErrorCode=0;
DWORD dwWritten=0;
//定義內(nèi)存流句柄,用于寫入照片數(shù)據(jù)
HANDLE hStream=INVALID_HANDLE_VALUE;
//1,打開學(xué)生數(shù)據(jù)庫
if(!tblStudent.DB_Open_Student())
{
//打開學(xué)生數(shù)據(jù)庫失敗
return FALSE;
}
//給字段屬性賦值
ZeroMemory(&pProps[0],sizeof(CEPROPVAL)*4);
//學(xué)生學(xué)號(hào)
pProps[0].propid=PID_NO;
pProps[0].val.lpwstr=LPWSTR(pRecStudent→szNo);
pProps[0].wFlags=0;
……
//寫入記錄
ceOid=CeWriteRecordProps(tblStudent.m_hDB,0,4,pProps);
if(ceOid==0)
{
dwErrorCode=GetLastError();
//如果 dwErrorCode=183,表示學(xué)生編號(hào)重復(fù)
if(dwErrorCode==ERROR_ALREADY_EXISTS)
{
TRACE(L"學(xué)生編號(hào)重復(fù) ");
}
else
{
TRACE(L"寫入記錄失敗,Error Code=%d ",dwErrorCode);
}
goto error;
}
EDB數(shù)據(jù)庫支持多種查找方式,比如指定位置查找,指定條件查找等,數(shù)據(jù)庫記錄的查找,通過CeSeek-DatabaseEx實(shí)現(xiàn)。CESeekDatabaseEx函數(shù)的 dwSeek-Type參數(shù)指定查找方式,常用的幾種查找方式如下:
直接查找指定位置的記錄(CEDB_SEEK_CEOID);
從開始位置查找(CEDB_SEEK_BEGINNING);
從最后位置查找(CEDB_SEEK_END);
從當(dāng)前位置查找(CEDB_SEEK_CURRENT);
查找第一條屬性等于指定值的記錄(CEDB_SEEK_VALUEFIRSTEQUAL);
查找下一條屬性等于指定值的記錄(CEDB_SEEK_VALUESMALLER);
查找小于等于指定屬性值的記錄(CEDB_SEEK_VALUESMALLEROREQUAL);
查找大于指定屬性值的記錄(CEDB_SEEK_VALUEGREATER);
查找大于或者等于指定屬性值的記錄(CEDB_SEEK_VALUEGREATEROREQUAL)[4]。
開發(fā)數(shù)據(jù)庫的是一個(gè)復(fù)雜的過程,只有掌握較多的知識(shí)才可以開發(fā)出功能強(qiáng)大,性能穩(wěn)定的數(shù)據(jù)庫。在數(shù)據(jù)庫開發(fā)過程中,通常會(huì)存在多個(gè)結(jié)構(gòu)體嵌套的情況,因而涉及到很多的結(jié)構(gòu)體和指針變量,在開發(fā)中要特別注意指針和內(nèi)存的問題,要防止內(nèi)存泄露,指針要及時(shí)清空。
[1]汪兵.Windows CE嵌入式高級(jí)編程及其實(shí)例詳解[M].北京:中國水利水電出版社,2008.
[2]田東風(fēng).Windows CE應(yīng)用程序設(shè)計(jì)[M].北京:機(jī)械工程出版社,2005.
[3]Microsoft.Microsoft MSDN mobile專區(qū)[EB/OL](2006 -07-18)[2013 -05 -16]http;//msdn.microsoft.com/en- us/windowsmobile/default.apsx,2006.
[4]沈建國.Windows CE 5.0 EDB數(shù)據(jù)庫的應(yīng)用與開發(fā)[D].重慶:重慶郵電大學(xué),2007.
[5]杜春雷.ARM體系結(jié)構(gòu)與編程[M].北京:清華大學(xué)出版社,2008.