在當(dāng)前的嵌入式工控產(chǎn)品中,數(shù)據(jù)庫(kù)得到了越來(lái)越多的應(yīng)用。通過(guò)數(shù)據(jù)庫(kù),可以非常方便地存儲(chǔ)和檢索數(shù)據(jù),極大地提高工作效率。英創(chuàng)公司基于WinCE的ARM9工控主板,提供了兩種類型的數(shù)據(jù)庫(kù),供客戶的應(yīng)用程序選擇。一種是WinCE自帶的數(shù)據(jù)庫(kù),主要面對(duì)需要存儲(chǔ)的數(shù)據(jù)量較小,數(shù)據(jù)結(jié)構(gòu)相對(duì)簡(jiǎn)單的應(yīng)用,例如系統(tǒng)的動(dòng)態(tài)配置文件,則使用起來(lái)非常合適。另一種則是在PC中最流行的SQL數(shù)據(jù)庫(kù),英創(chuàng)ARM9工控主板缺省配置的SQL數(shù)據(jù)庫(kù)版本為SQL CE2.0。在表一中,列出了WinCE自帶數(shù)據(jù)庫(kù)與SQL CE數(shù)據(jù)庫(kù)部分功能的對(duì)比,用戶可以根據(jù)自己的需要,選擇合適的數(shù)據(jù)庫(kù)。關(guān)于WinCE自帶數(shù)據(jù)庫(kù)的操作請(qǐng)參考《EVC高級(jí)編程及其應(yīng)用開(kāi)發(fā)》WinCE基礎(chǔ)數(shù)據(jù)庫(kù)編程部分。本文主要講解在eVC開(kāi)發(fā)環(huán)境下,以使用ADOCE 3.1為例詳細(xì)說(shuō)明開(kāi)發(fā)SQLCE本地?cái)?shù)據(jù)庫(kù)的方法。 表一:WinCE自帶數(shù)據(jù)庫(kù)與SQLCE數(shù)據(jù)庫(kù)功能對(duì)照表
WinCE 自帶數(shù)據(jù)庫(kù)
SQLCE 數(shù)據(jù)庫(kù)
開(kāi)發(fā)方式
使用 API 函數(shù)操作
使用 SQL 語(yǔ)句操作
數(shù)據(jù)類型
較少 (9 種 )
較多 (20 種 )
與 pc 端 SQL Sever 數(shù)據(jù)同步
不支持
支持
更改表字段
不支持
支持
在EVC環(huán)境下由于沒(méi)有提供專門的API函數(shù)對(duì)SQLCE進(jìn)行操作,需要通過(guò)ADOCE(Active Data Object for Windows CE)組件才能實(shí)現(xiàn)對(duì)SQLCE數(shù)據(jù)庫(kù)的操作。為了方便用戶使用SQLCE數(shù)據(jù)庫(kù),利用ADOCE組件技術(shù)(ADOCE介紹在附錄一中),針對(duì)數(shù)據(jù)庫(kù)操作中常用的功能,包括創(chuàng)打開(kāi)數(shù)據(jù)庫(kù)、建數(shù)據(jù)表等,英創(chuàng)提供了一個(gè)對(duì)SQLCE數(shù)據(jù)庫(kù)操作的管理類DBManager,應(yīng)用程序通過(guò)調(diào)用該類中提供的API函數(shù),就可以很方便的建立與SQLCE的鏈接、打開(kāi)數(shù)據(jù)庫(kù),并可以直接利用SQL語(yǔ)句來(lái)對(duì)數(shù)據(jù)庫(kù)進(jìn)行建立表、為表添加記錄以及查詢表中的記錄等功能。在eVC環(huán)境下通過(guò)DBManager類訪問(wèn)SQLCE數(shù)據(jù)庫(kù)模型如圖1所示。
圖1 EVC通過(guò)DBManager訪問(wèn)數(shù)據(jù)庫(kù)模型
一、DBManager類及派生類說(shuō)明 DBManager類主要提供打開(kāi)數(shù)據(jù)庫(kù)、執(zhí)行SQL語(yǔ)句等方法。其頭文件聲明如下: //函數(shù)功能:打開(kāi)數(shù)據(jù)庫(kù) //入口參數(shù):lpszFileName表示要打開(kāi)的數(shù)據(jù)庫(kù)名稱,為絕對(duì)路徑加文件名。 //出口參數(shù):無(wú) //返 回 值:TRUE:打開(kāi)數(shù)據(jù)庫(kù)成功;FALSE:打開(kāi)數(shù)據(jù)庫(kù)失敗 bool OpenDatabase(LPCTSTR lpszDBName); //函數(shù)功能:執(zhí)行SQL語(yǔ)句 //入口參數(shù):lpstrSql為要執(zhí)行SQL語(yǔ)句的字符串。 //出口參數(shù):無(wú) //返 回 值:TRUE:執(zhí)行SQL語(yǔ)句成功;FALSE:執(zhí)行SQL語(yǔ)句失敗 bool ExecSql(LPCTSTR lpstrSql); 如果想靈活使用DBManager類對(duì)數(shù)據(jù)庫(kù)操作,必須了解SQL語(yǔ)句,常用SQL語(yǔ)句可以參考附錄二中的內(nèi)容。但是,對(duì)于嵌入式工程師來(lái)說(shuō),有很多用戶對(duì)SQL語(yǔ)句并不了解,這樣,對(duì)用戶使用數(shù)據(jù)庫(kù)提高了門檻。在實(shí)際應(yīng)用中,嵌入式主板的主要任務(wù)是把采集工業(yè)現(xiàn)場(chǎng)的狀態(tài)并保存到數(shù)據(jù)庫(kù)中,如果想查看分析數(shù)據(jù),可以通過(guò)WebServer把數(shù)據(jù)庫(kù)信息傳輸?shù)紺lient端。為了方便不了解SQL語(yǔ)句的用戶使用數(shù)據(jù)庫(kù),我們?cè)诨怐BManager中提供了幾個(gè)虛函數(shù),并給出在派生類中實(shí)現(xiàn)虛函數(shù)的例子。這樣,使用API函數(shù)就可以實(shí)現(xiàn)打開(kāi)數(shù)據(jù)庫(kù)、創(chuàng)建表、插入記錄等操作。用戶可以根據(jù)要保存數(shù)據(jù)結(jié)構(gòu)修改虛函數(shù)就可以滿足用戶操作數(shù)據(jù)庫(kù)的要求,下面以一個(gè)實(shí)際示例說(shuō)明使用派來(lái)類的方法。
在工業(yè)現(xiàn)場(chǎng),用戶常常需要把現(xiàn)場(chǎng)的狀態(tài)保存起來(lái),例如,把AD采集的數(shù)據(jù)和開(kāi)關(guān)量保存起來(lái)。本文中,以英創(chuàng)的ETA197 AD模塊和ETA716 IO模塊為例,說(shuō)明數(shù)據(jù)庫(kù)的操作。ETA197、ETA716與嵌入式主板的連接如圖2所示。
圖2 嵌入式主板與ETA197、ETA716連接示意圖
根據(jù)實(shí)際情況,我們需要保存的信息有時(shí)間、IO輸出值、IO輸入值、8通道AD采樣值,根據(jù)我們的需要,我們?cè)O(shè)計(jì)ADDIOData數(shù)據(jù)結(jié)構(gòu)如下。 struct ADDIOData { CString adtime; //采集信息的時(shí)間 UCHAR dout; //IO輸出值 UCHAR din; //IO輸入值 float Advalue[8]; //AD采樣值 }; 根據(jù)此數(shù)據(jù)結(jié)構(gòu),我們實(shí)現(xiàn)了創(chuàng)建表和插入記錄的API函數(shù),函數(shù)聲明如下: class ADDataBase : public DBManager { public: //函數(shù)功能:創(chuàng)建表 //入口參數(shù):tablename表示要?jiǎng)?chuàng)建的表名。 //出口參數(shù):無(wú) //返 回 值:TRUE:創(chuàng)建表成功;FALSE:創(chuàng)建表失敗 bool CreateTable(LPCTSTR tablename); //函數(shù)功能:刪除表 //入口參數(shù):tablename表示要?jiǎng)h除的表名。 //出口參數(shù):無(wú) //返 回 值:TRUE:刪除表成功;FALSE:刪除表失敗 bool DeleteTable(LPCTSTR tablename); //函數(shù)功能:插入記錄 //入口參數(shù):tablename表示表名,fieldVal為記錄值結(jié)構(gòu)體 //出口參數(shù):無(wú) //返 回 值:TRUE:插入記錄成功;FALSE:插入記錄失敗 bool InsertRecord(LPCTSTR tablename,ADDIOData fieldVal); };二、使用DBManager類及派生類實(shí)現(xiàn)創(chuàng)建表、插入記錄等操作的順序?yàn)椋?/STRONG> (1)打開(kāi)數(shù)據(jù)庫(kù) (2)創(chuàng)建表 (3)插入記錄 ADDataBase dbm; CString DBFile=_T('\\nandflash\\emtronix.sdf'); CString TableName=_T('ADCollection'); UserInfo test; dbm.OpenDatabase(DBFile); //打開(kāi)數(shù)據(jù)庫(kù),參數(shù)為數(shù)據(jù)庫(kù)路徑名 dbm.CreateTable(TableName); //創(chuàng)建表 for (i=0;i<6;i++) //每秒鐘采集一次數(shù)據(jù) { test.dout=0x01<ISA_WriteUchar(EM9260_CS1,0x10,test.dout); //寫716輸出端口 ISA_ReadUchar(EM9260_CS1,0x10,&test.din); //讀716輸入端口 for (j=0;j<8;j++) { getADValue(j,0,&test.Advalue[j]); //得到8通道AD采樣值 } dbm.InsertRecord(TableName,test); //向tablename表中插入記錄 Sleep(1000); } 由上例可以看出,使用英創(chuàng)公司提供的DBManager的派生類,不必了解數(shù)據(jù)庫(kù)就可以方便地實(shí)現(xiàn)數(shù)據(jù)的存儲(chǔ)。 這種操作數(shù)據(jù)庫(kù)的方式不是十分靈活,對(duì)熟悉數(shù)據(jù)庫(kù)的用戶,可以使用DBManager類,執(zhí)行SQL語(yǔ)句,靈活對(duì)數(shù)據(jù)庫(kù)操作。關(guān)于DBManager類,可以參考源碼中注釋說(shuō)明。附錄一、ADOCE簡(jiǎn)介 ADOCE(Active Data Object for Windows CE)技術(shù)提供了高層數(shù)據(jù)庫(kù)應(yīng)用軟件的訪問(wèn)接口,可在eVC、eVB等高級(jí)語(yǔ)言環(huán)境中直接使用,ADOCE是一種易用的COM組件,關(guān)于COM組件的開(kāi)發(fā)與調(diào)用在《ARM9工控板在遠(yuǎn)程監(jiān)控中的應(yīng)用》系列文章中有詳細(xì)的說(shuō)明。ADOCE作為開(kāi)發(fā)WinCE數(shù)據(jù)庫(kù)應(yīng)用程度的面向?qū)ο蟮腃OM接口,其訪問(wèn)數(shù)據(jù)庫(kù)是通過(guò)訪問(wèn)OLE DB數(shù)據(jù)提供程序來(lái)進(jìn)行的,并且提供了一種對(duì)OLEDB數(shù)據(jù)提供程序的簡(jiǎn)單高層訪問(wèn)接口。ADOCE技術(shù)簡(jiǎn)化了OLE DB的操作,在OLE DB的程序中使用了大量的COM接口,而ADOCE則封裝了這些接口,所以,ADOCE是一種高層的訪問(wèn)技術(shù)。ADOCE的數(shù)據(jù)存儲(chǔ)模型如圖1 所示:
圖1 ADOCE的數(shù)據(jù)存儲(chǔ)模型
ADOCE支持Connection、Recordset、Field、Fields、Error對(duì)象,但不支持Command對(duì)象、Property對(duì)象以及Properties collection。下面介紹幾個(gè)重要的ADOCE對(duì)象。 連接對(duì)象(Connection) Connection對(duì)象建立一個(gè)對(duì)象數(shù)據(jù)源的數(shù)據(jù)交換環(huán)境,ADOCE允許建立對(duì)ACCESS數(shù)據(jù)源和SQLCE數(shù)據(jù)源的連接。 記錄集對(duì)象(Recordset) Recordset對(duì)象是ADOCE數(shù)據(jù)操作的核心,它是查詢結(jié)果的集合,可以通過(guò)這個(gè)結(jié)果集處理來(lái)自數(shù)據(jù)源的數(shù)據(jù),包括修改記錄、更新記錄、插入和刪除記錄等?梢酝ㄟ^(guò)Recordset的Open方法執(zhí)行SQL語(yǔ)句,實(shí)現(xiàn)數(shù)據(jù)庫(kù)的操作。 字段對(duì)象(Field) ·字段對(duì)象的每條記錄都由Fields組成,其中包括名稱、數(shù)據(jù)和值。 ·基于ADOCE的WinCE數(shù)據(jù)庫(kù)開(kāi)發(fā)程序包括以下基本步驟: ·創(chuàng)建Connection對(duì)象 ·打開(kāi)數(shù)據(jù)源,建立同數(shù)據(jù)源的連接 ·創(chuàng)建Record對(duì)象 ·將Recordset的連接字符串設(shè)置到Connection對(duì)象中 ·使用SQL命令 ·通過(guò)Recordset對(duì)象完成結(jié)果記錄集的操作 ·終止連接附錄二、SQL語(yǔ)句語(yǔ)法說(shuō)明 SQL是Structure Query Language結(jié)構(gòu)化查詢語(yǔ)言的縮寫,通過(guò)SQL語(yǔ)句的執(zhí)行,可以對(duì)數(shù)據(jù)庫(kù)內(nèi)容(表及記錄)進(jìn)行修改或查詢,因此數(shù)據(jù)庫(kù)的操作就是執(zhí)行SQL語(yǔ)句。下面簡(jiǎn)要介紹下幾個(gè)重要的SQL語(yǔ)句。 1、Create Table語(yǔ)句功能是創(chuàng)建表,其語(yǔ)法格式如下: Create Table 表名稱 (字段名稱 數(shù)據(jù)類型 [(字段長(zhǎng)度)] [,字段名稱 數(shù)據(jù)類型 [(字段長(zhǎng)度)] ,[ PRIMARY KEY | UNIQUE ] ] 例如: CREATE TABLE Products (ProductID int,Name nvarchar(255), PRIMARY KEY (ProductID) 2、Drop Table語(yǔ)句的功能是將一個(gè)現(xiàn)存于數(shù)據(jù)庫(kù)內(nèi)的表刪除,其所使用的語(yǔ)法與格式如下所示: Drop Table 表名稱 3、Select語(yǔ)句可以對(duì)表的記錄作查詢、統(tǒng)計(jì)。由于Select語(yǔ)句使用比較靈活,我們以幾個(gè)具體的例子講價(jià)Select的用法。 Select 字段名稱 [,字段名稱] From 表名稱 其中,F(xiàn)rom關(guān)鍵詞是設(shè)置來(lái)源表名稱,使用時(shí)可以設(shè)置使用一個(gè)或多個(gè)表,而表名稱間以逗號(hào)分隔。在搜尋結(jié)果中取出所需的字段內(nèi)容,設(shè)置的字段名稱以逗號(hào)分隔,如果要取得表上的所有字段,可直接用“*”表示。 SELECT * FROM Products WHERE ProductID='02' Where關(guān)鍵詞是設(shè)置查詢記錄條件,用以取得所有符合設(shè)置條件內(nèi)容的記錄。在條件設(shè)置中可以使用 > 、<、=等比較符號(hào),而對(duì)于多項(xiàng)條件的判斷也可以利用AND,OR等邏輯操作數(shù)來(lái)連接。 4、插入記錄 INSERT INTO 表名[(field1[, field2[, ...]])] VALUES (value1[, value2[, ...]] 例如:INSERT INTO Products (ProductID,Name) VALUES (1,'EM9000嵌入式模塊') 5、刪除記錄 DELETE FROM 表名 WHERE criteria 例如:DELETE FROM 表名 WHERE ProdutcID=01 6、更新記錄 UPDATE 表名 SET newvalue WHERE criteria; 例如:Update Products set Name=’EM9161嵌入式主板’ where ProdcutID=01 在eVC環(huán)境下,對(duì)數(shù)據(jù)的開(kāi)發(fā),其實(shí)就是通過(guò)ADOCE COM組件執(zhí)行SQL語(yǔ)句的過(guò)程。為了使用戶方便的使用ADOCE,我們提供了DBManager類,通過(guò)此類,可以方便的建立與數(shù)據(jù)庫(kù)的連接、執(zhí)行sql語(yǔ)句等操作。