Windows Embedded Compact 7數據庫開發(下)

8.1.1 建立刪除數據庫數據庫

將數據庫卷掛載好以後,就能夠在卷內新建立一個EDB數據庫,調用函數CeCreateDatabaseWithProps()實現:數組

CEOID CeCreateDatabaseWithProps(緩存

  PCEGUID pGuid,服務器

  CEDBASEINFOEX* pInfo,數據結構

  DWORD cProps,併發

  CEPROPSPEC* prgPropside

);函數

l 參數pGuid爲掛載數據庫的全局標識CEGUID大數據

l 參數pInfo指定數據庫的屬性,爲一個指向結構體CEDBASEINFOEX的指針。ui

參數cProps指定參數prgProps數組的元素個數。

l 參數prgProps指定新建數據庫的屬性,爲一個CEPROPSPEC結構體數組。在EDB中必須設置這些屬性,才能向數據庫內寫入數據,結構體CEPROPSPEC的定義以下:

typedef struct CEPROPSPEC {

  WORD wVersion;

  CEPROPID propid;

  DWORD dwFlags;

  LPWSTR pwszPropName;

  DWORD cchPropName;

} CEPROPSPEC;

n 成員wVersion爲結構體版本號,必須設置爲1

n 成員propid爲字段ID,表示數據庫中的字段。

n 成員dwFlags爲字段標誌,能夠取下面值之一或組合:DB_PROP_COMPRESSED(將字段壓縮存儲)和DB_PROP_NOTNULL(字段不能爲空,也不能設置爲NULL)

成員 pwszPropName爲字段的名稱,爲可選。若是沒有指定字段的名稱,系統將產生一個內部名稱。

n 成員cchPropName爲可選的字段名稱的長度,最大可爲CEDB_MAXDBASENAMELEN (128).

若是建立EDB數據庫成功,函數將返回數據庫的對象標誌(OID);建立失敗將返回NULL。調用GetLastError()獲取錯誤信息,可能的錯誤值有:

n E_FAIL: CEDBASEINFOEX結構體中指定數據庫名稱的szDbaseName成員的長度超過CEDB_MAXDBASENAMLEN。

n ERROR_ACCESS_DENIED: 試圖建立一個包含2個可排序主鍵的數據庫

n ERROR_ALREADY_EXISTS: 參數prgProps包含的某個字段ID或字段名字已經存在。

n ERROR_BAD_LENGTH: 某個字段名稱的長度超過128

n ERROR_DISK_FULL: 磁盤空間不足,沒法建立數據庫。

n ERROR_DUP_NAME: 指定名字的數據庫在卷中已經存在。

n ERROR_INVALID_PARAMETER: 某個參數不合法。

n ERROR_NOT_FOUND: 參數pGuid指定的卷不存在。

n ERROR_NOT_SUPPORT: CEDBASEINFOEX結構體中使用CEDB不支持的值,如CEDB_VALIDMODTIMECEDB_SYSTEMDB

用戶還能夠刪除掛載的數據庫卷內的指定數據庫,經過函數CeDeleteDatabase()實現:

BOOL CeDeleteDatabase( 

  PCEGUID pGuid

  CEOID oid

);

l 參數pGuid指定將被從中刪除數據庫的掛載數據庫卷的CEGUID

l 參數oid指定將被刪除的數據庫的對象ID,這個數據庫在指定的數據庫卷內必須存在。

刪除數據庫成功,函數返回TRUE;失敗返回FALSE。注意用戶不能刪除一個正在打開的數據庫。

8.1.2 建立會話

Windows CE系統中,只有EDB數據庫支持事務(Transaction)處理。事務保證對數據庫的一系列更新操做做爲一個原子操做提交,要麼全部更新都生效,要麼全不生效,事務防止數據庫因爲奔潰或掉電致使的部分更新而進入不一致狀態。爲了支持數據庫的事務功能,須要使用基於會話(Session)鏈接並打開EDB數據庫。Win 32中的CeCreateSession()函數爲EDB數據庫建立一個會話對象:

HANDLE CeCreateSession(

  CEGUID* pGuid

);

l 參數pGuid爲掛載的數據庫卷的全局標識CEGUID,這個值不能設置爲NULL

若是建立會話對象成功,函數返回新建會話對象的句柄;若是調用失敗則返回INVALID_HANDLE_VALUE。調用函數GetLastError()獲取出錯信息,可取的錯誤值有:

ERROR_INVALID_PARAMETER參數pGuid被設置爲NULL

ERROR_NOT_FOUND: 指定的卷沒有被掛載或參數pGuid爲一個非法的GUID

使用會話完畢,須要調用函數CloseHandle()關閉會話句柄,釋放資源。

8.1.3 打開數據庫

在對數據庫進行查詢或更新操做以前,須要先打開數據庫。能夠有兩種打開數據庫的方式:基於會話鏈接的支持事務功能的方式打開數據庫,和不支持事務的方式打開數據庫。

這裏只介紹前者,在建立好會話對象後,函數CeOpenDatabaseInSession()使用基於會話鏈接的方式打開數據庫:

HANDLE CeOpenDatabaseInSession(

  HANDLE hSession,

  PCEGUID pGuid,

  PCEOID poid,

  LPWSTR lpwszName,

  SORTORDERSPECEX* pSort,

  DWORD dwFlags,

  CENOTIFYREQUEST* pRequest

);

l 參數hSession指定使用的會話對象句柄。能夠將這個參數設置爲NULL,這時系統會自動新建一個會話,並且對打開數據庫的任一更新操做都會被當即提交給數據庫,保證每個更新操做的原子性。若是不爲NULL,那麼建立該會話對象的數據庫卷的CEGUID必須與參數pGuid指定的一致,不然函數調用將失敗。

l 參數pGuid指定掛在數據庫卷的CEGUID。若是這個參數設置爲一個合法的GUID,那麼將使用指定的卷;若是這個參數被設置爲由CREATE_INVALIDEDBGUID宏返回的非法值,那麼後面的poid參數將被忽略,系統將搜索全部的掛載數據庫卷並使用第一個名字與參數lpwszName指定的匹配的數據庫卷。

l 參數poid爲輸入輸出參數,返回打開的數據庫對象標識(OID)。既能夠經過OID打開數據庫,也能夠經過名稱打開。將poid設置爲非0的數據庫OID,將忽略參數lpwszName指定的數據庫名。若是但願經過名稱來打開數據庫,就將這個參數設置爲0,函數完成後,這個參數將返回指定數據庫對象的OID

l 參數lpwszName指定將打開的數據庫的名稱。當參數poid被設置爲0時,將使用這個名稱和pGuid來打開數據庫。

l 參數pSort指定數據庫打開時使用的排序規則。若是這個參數被設置爲NULL表示不使用任何排序規則。

l 參數dwFlags能夠取值爲0, CEDB_AUTOINCREMENT或EDB_USE_CEDB_WRITE_SEMANTICS。當取值爲CEDB_AUTOINCREMENT時,表示當用戶調用CeReadRecordPropsEx()讀取一條記錄時,數據庫的當前指針會自動地往下移動到排序順序的下一條記錄位置。當取值爲0時,表示讀取一條記錄時,數據庫的當前指針不會自動往下移動,而須要用戶手工移動到下一條記錄位置。當取值爲EDB_USE_CEDB_WRITE_SEMANTICS時,表示將已在掛載卷內存在的數據庫打開並添加動態屬性。

l 參數pRequest爲指向數據結構CENOTIFYREQUEST的指針,用於指定當其餘線程或進程對數據庫進行修改時,如何發送通知消息到指定的窗口。若是將這個參數設置爲NULL,表示應用不須要收到任何通知消息。結構體CENOTIFYREQUEST的定義以下:

typedef struct _CENOTIFYREQUEST {

  DWORD dwSize;

  HWND hwnd;

  DWORD dwFlags;

  HANDLE hHeap;

  DWORD dwParam;

} CENOTIFYREQUEST;

其中,成員dwSize指定結構CENOTIFYREQUEST的大小,成員hwnd指定用於接收通知消息的窗口句柄,成員dwFlags指定處理消息的方式,成員hHeap爲一個堆句柄,用於爲接收到消息分配空間,若是設置爲NULL,系統將在進程的默認堆上分配內存空間。最後一個成員dwParam爲用戶自定義的返回參數。

若是打開數據庫成功,將返回被打開的數據庫的句柄。打開數據庫出錯將返回INVALID_HANDLE_VALUE,GetLastError()函數將返回出錯信息,可能的值如表8-3所示。

返回錯誤碼

說明

ERROR_FILE_NOT_FOUND

參數poidlpwszName指定的數據庫不存在

ERROR_INVALID_HANDLE

參數hSession值爲INVALID_HANDLE_VALUE.

ERROR_INVALID_PARAMETER

其它的參數內至少一個爲非法值

ERROR_NOT_ENOUGH_MEMORY

內存空間不足,沒法分配數據庫句柄

ERROR_NOT_FOUND

參數pGuid指定的數據庫卷不存在

8.1.4 獲取數據庫的會話

若是但願從打開的數據庫句柄獲取對應的會話信息,調用函數CeGetDatabaseSession()實現:

HANDLE CeGetDatabaseSession(

  HANDLE hDatabase

);

l 參數hDatabase爲打開的數據庫句柄,必須經過調用CeOpenDatabaseInSession()獲取。

若是函數調用成功,返回會話句柄。失敗則返回INVALID_HANDLE_VALUE。可能返回的錯誤碼有:

l ERROR_INVALID_HANDLE:參數hDatabase被設置爲NULLINVALID_HANDLE_VALUE。

l ERROR_INVALID_PARAMETER:參數hDatabase不爲NULL,可是指向一個非法的數據庫卷。

l ERROR_NOT_ENOUGH_MEMORY:內存空間不足。

8.1.5 查找記錄

數據庫打開成功以後,就能夠對其進行讀寫訪問。可是在訪問以前,須要首先將數據庫指針移動到指定的記錄位置,就是首先須要定位到用戶感興趣的記錄位置,函數CeSeekDatabaseEx()用於定位到一條記錄:

CEOID CeSeekDatabaseEx(

  HANDLE hDatabase,

  DWORD dwSeekType,

  DWORD dwValue,

  WORD wNumVals,

  LPDWORD lpdwIndex

);

l 參數hDatabase爲打開的數據庫句柄。

l 參數dwSeekType指定定位記錄的方式,可取值如表8-4所示。

8-4 可取的定位數據庫記錄的方式

定位方式

說明

CEDB_SEEK_BEGINNING

從數據庫的開始位置依次日後查找,直到定位到指定的記錄,參數dwValue指定從開始位置的記錄下標

CEDB_SEEK_CEOID

根據記錄的對象ID(OID)來定位記錄,參數dwValue指定記錄的OID,這種類型的定位操做很是高效

CEDB_SEEK_CURRENT

從數據庫指針的當前位置開始向前或向後查找指定個數的記錄,參數dwValue指定移動的個數,若是dwValue爲正數,將向前移動查找;若是爲負數,將向後移動查找。

CEDB_SEEK_END

從數據庫的結束位置開始向後查找,參數dwValue指定移動的記錄個數

CEDB_SEEK_PREFIX

查找數據時使用前綴,只能用於字符串和BLOB數據類型

CEDB_SEEK_VALUEFIRSTEQUAL

從數據庫的開始位置向後查找直到第一個值與指定的值相等的記錄,該值爲參數dwValue指向的CEPROPVAL結構數組和參數wNumVals指定的數組大小。若是定位操做失敗,數據庫指針將留在數據庫結束位置,函數將返回0

CEDB_SEEK_VALUEGREATER

從數據庫開始位置向後查找直到找到第一個「大於」指定值的記錄。注意無論排序方式老是向後查找。對於升序,這個將找到大於指定值的最小的記錄。而對於降序,將找到小於指定值的最大的記錄。若是沒有知足條件的記錄,數據庫指針將留在數據庫結束位置,函數返回0

CEDB_SEEK_VALUEGREATEROREQUAL

從數據庫的開始位置向後查找,直到第一個「大於等於」指定值的記錄

CEDB_SEEK_VALUENEXTEQUAL

從數據庫指針的當前位置開始,按照排列次序指向下查找一個位置,並判斷這下一個記錄的值是否與指定值相等。若是想等,返回下一個記錄的對象ID;不然將返回0,數據庫指針留在數據庫末尾。

CEDB_SEEK_VALUESMALLER

CEDB_SEEK_VALUEGREATER相對,從數據庫末尾位置開始老是向前查找,知道第一個「小於」指定值的記錄。對於升序,找到小於指定值的最大的記錄;對於降序,找到大於指定值的最小記錄。若是知足條件的記錄找不到,數據庫指針將留在數據庫的末尾位置,函數返回0

CEDB_SEEK_VALUESMALLEROREQUAL

從數據庫末尾位置開始向前查找,直到第一個「小於等於」指定值的記錄

l 參數dwValue根據不一樣的定位方式,可能指定查找的偏移量,也可能爲指向要搜索的屬性值數組的指針,屬性值由結構體CEPROPVAL表示,定義以下:

typedef struct _CEPROPVAL {

  CEPROPID propid;

  WORD wLenData;

  WORD wFlags;

  CEVALUNION val;

} CEPROPVAL, * PCEPROPVAL;

成員propid表明屬性的標識,高字(word)部分爲應用自定義的標識,低字部分爲預約義的常量值,表明成員val的數據類型,低字部分的值可取爲表10-4所示。成員wLenData被保留,必須設置爲0。成員wFlags指定字段的屬性,在CeSeekDatabaseEx()函數中能夠忽略。成員val爲字段的值,是數據庫支持的不一樣數據類型組成的一個聯合體。

10-4 屬性的數據類型

說明

CEVT_BLOB

CEBLOB結構

CEVT_BOOL

Boolean

CEVT_FILETIME

FILETIME結構

CEVT_I2

16位帶符號整數

CEVT_I4

32位帶符號整數

CEVT_LPWSTR

爲以null結束的字符串

CEVT_R8

64位帶符號整數

CEVT_UI2

16位無符號整數

CEVT_UI4

32位無符號整數

l 參數wNumVals表示在參數dwValue裏的CEPROPVAL結構體數組大小。

l 參數lpdwIndex爲輸出參數,用於返回記錄在數據庫中的索引,若是不須要獲取記錄的索引值,將這個參數設置爲NULL

定位記錄成功,函數將返回記錄的對象ID;失敗則返回0

下面的代碼演示如何在數據庫中查找寬度屬性小於等於80的第一條記錄:

CEOID oid;

DWORD dwIndex;

CEPROPVAL property;

//首先將數據庫指針移動到起始位置

Oid = CeSeekDatabaseEx(hDB, CEDB_SEEK_BEGINNING, 0, 1, &dwIndex);

//設置定位條件

Property.propid = PID_WIDTH;

Property.wLenData = 0;

Property.wFlags = 0;

Property.val.lVal = 80;

Oid = CeSeekDatabaseEx(hDB, CEDB_SEEK_VALUESMALLEROREQUAL,

  (DWORD)&property, 1, &dwIndex);

If(oid == 0)

{

//沒有找到知足條件的記錄

}

Else{

//找到記錄,參數dwIndex返回該記錄在數據庫中的索引

}

8.1.6 讀取記錄數據

在定位到指定的記錄後,就能夠對記錄進行讀取或寫入操做了。一條記錄包含多個屬性(在數據庫中爲列),函數CeReadRecordPropsEx()讀取當前記錄的屬性值:

CEOID CeReadRecordPropsEx(
   HANDLE hDbase,
   DWORD dwFlags,
   LPWORD lpcPropID,
   CEPROPID* prgPropID,
   LPBYTE* lplpBuffer,
   LPDWORD lpcbBuffer,
   HANDLE hHeap
    );

l 參數hDbase爲打開的數據庫句柄。

l 參數dwFlags爲讀取標識,若是設置爲CEDB_ALLOWREALLOC,系統將調用LocalAlloc()函數爲參數ppbBuffer指定緩衝分配內存空間。若是緩衝空間不足,服務器將爲緩衝從新分配空間。若是設置爲0,表示系統在讀取記錄屬性時,不會進行內存操做。

參數lpcPropID爲輸入輸出參數,指定由參數prgPropID表示屬性ID數組包含的元素個數,若是參數prgPropID被設置爲NULL,那麼這個參數將返回實際讀取的屬性個數。

參數prgPropID爲一個指向包含屬性ID數組的指針,指定須要讀取的字段。若是這個參數被設置爲NULL,將讀回記錄中的全部字段,而此時lpcPropID將返回字段的個數。

參數lplpBuffer指定用於接收讀回的字段的緩衝區,注意這個參數不是指向緩衝區的指針,而是指向緩衝區指針的指針,這是由於系統可能從新分配緩衝區,函數將會修改指向緩衝區的指針。每次使用完緩衝區後,都必須釋放。

l 參數lpcbBuffer爲輸入輸出參數,表示參數lplpBuffer指定的緩衝區的字節數。函數返回時,這個參數將獲取實際拷貝到緩衝區內的數據量。若是緩衝區過小沒法容下記錄數據,而且沒有設置系統自動從新分配,這個參數能夠用於計算獲取數據的緩衝區大小。

l 參數hHeap爲指向應用建立的堆句柄,用於系統從新分配內存。這個參數只在dwFlags被設置爲CEDB_ALLOWREALLOC時纔有意義。

若是讀取記錄數據成功,函數將返回記錄的對象ID(OID);失敗將返回0。調用GetLastError()函數獲取錯誤碼信息,可能的值爲:

ERROR_INSUFFICIENT_BUFFER:表明參數dwFlags沒有包含CEDB_ALLOWREALLOC標識,並且參數lpcbBuffer指定的緩衝區大小不夠大,沒法接收字段數據。此時函數返回時,參數lpcbBuffer將包含用於讀取字段數據的正確緩衝區大小。

ERROR_INVALID_HANDLE:表明非法的數據庫句柄,參數hDbase爲NULLINVALID_HANDLE_VALUE

ERROR_INVALID_PARAMETER:表明下面三個參數至少其中一個被設置爲NULL: lpcPropID, lplpBuffer,lpcbBuffer。

ERROR_KEY_DELETED:表明當前記錄已經被刪除

ERROR_NO_DATA:表明記錄不包含指定的請求字段。

ERROR_NO_MORE_ITEMS:表明數據庫指針當前不指向任何一個記錄,須要首先定位記錄

ERROR_NOT_ENOUGH_MEMORY:表明內存分配失敗。

ERROR_SHARING_VIOLATION:表明當前記錄被其它進程鎖住,沒法讀取。

若是數據庫在打開時設置了CEDB_AUTOINCREMENT,那麼這個函數在讀取記錄數據成功後,數據庫指針將自動往下移動到下一個記錄位置。

8.1.7 寫記錄

出了讀取記錄的數據外,用戶還能夠對記錄值進行更新或者向數據庫內插入一條新的記錄,函數CeWriteRecordProps()實現寫記錄:

CEOID CeWriteRecordProps(

  HANDLE hDatabase,

  CEOID oidRecord,

  WORD cPropID,

  CEPROPVAL* prgPropVal

);

l 參數hDatabase指定打開的數據庫句柄。

l 參數oidRecord指定將被更新的記錄的對象ID,這個參數能夠設置爲0,這時將在數據庫中新建一個記錄,並使用指定的字段值填充新建的記錄。

l 參數cPropID指定字段數組的字段個數,參數prgPropVal指定字段數組。

l 參數prgPropVal指向包含將寫入到記錄中的字段值的數組,每一個字段使用CEPROPVAL結構表示。

若是寫入記錄成功,函數返回被寫入記錄的對象ID;失敗將返回0

注意寫入記錄將被系統緩存直到將數據庫回寫,這個函數將數據庫指針留在被寫入的記錄位置。

8.1.8 刪除記錄

刪除數據庫中的一條記錄使用函數CeDeleteRecord()實現:

BOOL CeDeleteRecord(

  HANDLE hDatabase,

  CEOID oidRecord

);

l 參數hDatabase爲打開的數據庫句柄。

l 參數oidRecord爲將被刪除的記錄的OID,這個參數不能被設置爲NULL

刪除記錄成功,函數返回TRUE;失敗將返回FALSE,可能的錯誤碼爲:

ERROR_INVALID_HANDLE:參數hDatabase被設置爲NULLINVALID_HANDLE_VALUE

ERROR_INVALID_PARAMETER:參數oidRecord被設置爲NULL或非法值

ERROR_NOT_FOUND:參數oidRecord指定的記錄不存在。

ERROR_SHARING_VIOLATION:表示記錄被其它進程鎖定,發送衝突。

若是數據庫在打開時沒有設置CEDB_AUTOINCREMENT標誌,並且刪除的記錄爲當前數據庫指針指向的記錄時,那麼下一次讀取記錄的操做將失敗(須要從新定位記錄)。若是設置了CEDB_AUTOINCREMENT標誌,系統將自動日後移動數據庫指針到下一個記錄位置。

8.1.9 使用流讀寫記錄

前面介紹的直接讀寫數據庫記錄,爲用戶提供比較直觀的訪問接口,可是這種方式只對小數據量的訪問比較合適,若是須要訪問大量的數據,就會比較低效。在EDB中還支持對記錄的流讀寫,這對於大數據量的記錄讀寫是頗有用。首先將整個記錄的數據都放到一個連續的數據流中,而不是以一個一個數據塊的方式讀寫。在使用流讀寫記錄以前須要先打開流,函數CeOpenStream()爲一個記錄打開流對象:

HANDLE CeOpenStream(

    HANDLE hDatabase,

    CEPROPID propid,

    DWORD dwMode

);

l 參數hDatabase爲打開的數據庫句柄。

l 參數propid指定將被以流對象打開的屬性的屬性ID,屬性必須爲CEVT_STREAM類型。

參數dwMode指定流對象的訪問權限,可取如下兩種值:

GENERIC_READ對流對象提供只讀訪問權限,不容許寫入。

GENERIC_WRITE對流對象提供讀寫訪問權限。

打開流對象成功,函數將返回流對象的句柄;失敗則返回INVALID_HANDLE_VALUE

打開流對象後,就能夠對流對象進行讀寫操做,函數CeStreamRead()用於從流對象中讀取數據:

BOOL CeStreamRead(

  HANDLE hStream,

  LPBYTE lprgbBuffer,

  DWORD cbRead,

  LPDWORD lpcbRead

);

l 參數hStream爲打開的流對象。

l 參數lprgbBuffer指定用於接收從流內讀取數據的緩衝區。

l 參數cbRead指定須要從流對象讀取的數據量,單位爲字節。

l 參數lpcbRead爲輸出參數,返回本次讀取操做實際從流對象中讀取的數據量。

從流對象中讀取數據成功,函數返回TRUE,失敗則返回FALSE

若是打開流對象時指定的讀寫權限,就能夠向流對象內寫入數據,函數CeStreamWrite()用於從流的當前位置開始向流對象內寫入指定大小的數據:

BOOL CeStreamWrite(

  HANDLE hStream,

  LPBYTE lprgbBuffer,

  DWORD cbWrite,

  LPDWORD lpcbWritten

);

l 參數hStream爲打開的流對象句柄。

l 參數lprgbBuffer爲包含將要寫入到流對象中數據的緩衝區。

l 參數cbWrite指定將要寫入到流對象中的數據量,單位爲字節。

l 參數lpcbWritten爲輸出參數,返回實際寫入到流對象中的數據量。

向流對象中寫入數據成功,函數返回TRUE;失敗則返回FALSE

實際上流對象內部也維護一個當前指針,而CeStreamRead()CeStreamWrite()函數老是從當前指針指向的位置開始讀取或寫入數據。若是用戶須要從其它的位置開始讀取寫入數據,能夠調用CeStreamSeek()函數來顯式設置當前指針的位置:

BOOL CeStreamSeek(

  HANDLE hStream,

  DWORD cbMove,

  DWORD dwOrigin,

  LPDWORD lpcbNewOffset

);

l 參數hStream爲打開的流對象句柄。

l 參數cbMove指定相對於參數dwOrigin指定的起始參考位置移動的字節數。

l 參數dwOrigin指定移動的起始參考位置,可取值爲:

STREAM_SEEK_CUR以當前指針位置做爲起始參考位置。這時,參數cbMove做爲有符號數,正數表示向前(向末尾位置方向)移動,而負數表示向後(向開始位置方向)移動。

STREAM_SEEK_END以流對象的末尾位置爲起始參考位置,向前移動。

STREAM_SEEK_SET以流對象的起始位置爲起始參考位置,向後移動。

參數lpcbNewOffset爲輸出參數,若是移動指針位置成功,返回新的指針位置相對於流對象起始位置的偏移量。若是不須要,能夠將這個參數設置爲NULL

移動流對象指針位置成功,函數返回TRUE;失敗返回FALSE。須要注意是,這個函數不負責檢測移動的偏移量是否合法,即便用戶指定的偏移量超出流對象的範圍,這個函數仍是會返回TRUE。好比一個流對象大小爲80字節,可是指定將指針移動到相對開始位置的160字節,函數調用仍是會成功返回,可是後續的操做將失敗。利用這個函數還能夠獲取流對象的大小信息,具體方式是,將參數dwOrigin設置爲STREAM_SEEK_END,參數cbMove設置爲0,這樣函數返回時,參數lpcbNewOffset將包含流的大小。

Windows CE還容許用於動態地改變流對象的大小,函數CeStreamSetSize()用於從新設置流對象的大小:

BOOL CeStreamSetSize(

  HANDLE hStream,

  DWORD cbSize

);

l 參數hStream爲打開的流對象句柄。

l 參數cbSize指定流對象新的大小。

改變流對象大小成功,函數返回TRUE;失敗返回FALSE。注意只能對讀寫訪問權限的流對象從新設置大小,就是說打開流對象時須要指定爲GENERIC_WRITE,不然函數調用將失敗。

對流對象進行寫入操做,實際上只是將數據寫入到內存中,並無寫回到數據庫中。爲了將數據寫回到數據庫中,須要調用函數CeStreamSaveChanges()來實現:

BOOL CeStreamSaveChanges(

  HANDLE hStream

);

l 參數hStream爲打開的流對象句柄。

將流對象寫回到數據庫成功,函數返回TRUE;不然返回FALSE。注意一旦將流對象寫回到數據庫,流對象將自動變爲只讀模式,再也不容許對流對象進行寫入操做。

前面介紹的操做流對象的函數都是經過流對象句柄來完成,一旦使用流句柄完畢,須要將其關閉,函數CloseHandle()關閉流並釋放流對象。

8.1.10 事務操做

事務是數據庫提供的基本功能。事務時做爲單個邏輯工做單元執行的一系列操做,事務必須具備四個屬性:原子性、一致性、隔離性和持久性:

l 原子性:事務必須是原子工做單元,對數據的一系列修改,要麼所有執行,要麼所有都不執行,這也是咱們最常常提到的特性。

l 一致性:事務完成時,必須使全部的數據都保持一致狀態。

l 隔離性:由併發事務所做的修改必須與任何併發事務所做的修改隔離。

l 持久性:事務完成(提交)後,對系統的影響是永久性的。

Windows CE中,EDB數據庫引擎提供事務支持,使用事務必須首先獲取會話句柄,使用事務的通常步驟是,啓動事務,對數據庫執行一系列讀寫操做,最後提交事務。啓動事務經過函數CeBeginTransaction()實現:

BOOL CeBeginTransaction(

  HANDLE hSession,

  CEDBISOLATIONLEVEL isoLevel

);

l 參數hSession爲會話句柄。

l 參數isoLevel指定事務操做的隔離級別,EDB數據庫引擎支持如下3種:

CEDB_ISOLEVEL_DEFAULT或者CEDB_ISOLEVEL_READCOMMITTED:當前事務正在進行更改的數據不容許其它事務讀取,直到事務提交完成。

CEDB_ISOLEVEL_REPEATABLEREAD:當前事務正在進行更改的數據容許其它事務讀取,可是不容許其它事務更改。

CEDB_ISOLEVEL_SERIALIZABLE:當前事務正在訪問(包括讀取和寫入)的數據,其它事務不能併發訪問(讀寫都不容許),只能串行化訪問。

啓動事務成功,函數返回TRUE;不然失敗返回FALSE。注意EDB不容許建立嵌套事務,若是一個會話已經在一個(未提交)的事務中,使用這個會話再啓動事務將致使失敗。

結束一個事務使用函數CeEndTransaction(),這裏能夠指定是提交全部的操做仍是進行回滾:

BOOL CeEndTransaction(

  HANDLE hSession,

  BOOL fCommit

);

l 參數hSession爲會話句柄。

l 參數fCommit指定是否將事務操做提交到數據庫中。若是設置爲TRUE,表示提交事務;設置爲FALSE表示回滾,事務中的操做所有取消。注意即便將事務提交到數據庫中,仍是須要等到調用CeFlushDBVol()回寫數據庫卷才能寫回到磁盤中。

提交事務成功,函數返回TRUE;失敗則返回FALSE。若是指定的會話句柄沒有在事務(調用CeBeginTransaction)中,函數調用將失敗。

8.1 總結

本章介紹了Windows CE7中數據庫的基本概念,尤爲針對EDB數據庫,介紹EDB數據庫支持的類型,限制。而後介紹EDB數據庫開發的API,包括掛載及卸載數據庫卷,枚舉數據庫卷和數據庫,查詢對象信息,回寫數據庫卷,建立刪除數據庫。建立會話,查找記錄,讀寫數據庫內的記錄,使用流讀寫記錄,以及怎麼使用事務操做。

相關文章
相關標籤/搜索