8.1.1 建立刪除數據庫數據庫
將數據庫卷掛載好以後,就能夠在卷內新建立一個EDB數據庫,調用函數CeCreateDatabaseWithProps()實現:數組
CEOID CeCreateDatabaseWithProps(緩存
PCEGUID pGuid,服務器
CEDBASEINFOEX* pInfo,數據結構
DWORD cProps,併發
CEPROPSPEC* prgPropside
);函數
l 參數pGuid爲掛載數據庫的全局標識CEGUID大數據
l 參數pInfo指定數據庫的屬性,爲一個指向結構體CEDBASEINFOEX的指針。ui
l 參數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)。
n 成員 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_VALIDMODTIME或CEDB_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()獲取出錯信息,可取的錯誤值有:
n ERROR_INVALID_PARAMETER: 參數pGuid被設置爲NULL。
n 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 |
參數poid或lpwszName指定的數據庫不存在 |
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被設置爲NULL或INVALID_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,表示系統在讀取記錄屬性時,不會進行內存操做。
l 參數lpcPropID爲輸入輸出參數,指定由參數prgPropID表示屬性ID數組包含的元素個數,若是參數prgPropID被設置爲NULL,那麼這個參數將返回實際讀取的屬性個數。
l 參數prgPropID爲一個指向包含屬性ID數組的指針,指定須要讀取的字段。若是這個參數被設置爲NULL,將讀回記錄中的全部字段,而此時lpcPropID將返回字段的個數。
l 參數lplpBuffer指定用於接收讀回的字段的緩衝區,注意這個參數不是指向緩衝區的指針,而是指向緩衝區指針的指針,這是由於系統可能從新分配緩衝區,函數將會修改指向緩衝區的指針。每次使用完緩衝區後,都必須釋放。
l 參數lpcbBuffer爲輸入輸出參數,表示參數lplpBuffer指定的緩衝區的字節數。函數返回時,這個參數將獲取實際拷貝到緩衝區內的數據量。若是緩衝區過小沒法容下記錄數據,而且沒有設置系統自動從新分配,這個參數能夠用於計算獲取數據的緩衝區大小。
l 參數hHeap爲指向應用建立的堆句柄,用於系統從新分配內存。這個參數只在dwFlags被設置爲CEDB_ALLOWREALLOC時纔有意義。
若是讀取記錄數據成功,函數將返回記錄的對象ID(OID);失敗將返回0。調用GetLastError()函數獲取錯誤碼信息,可能的值爲:
n ERROR_INSUFFICIENT_BUFFER:表明參數dwFlags沒有包含CEDB_ALLOWREALLOC標識,並且參數lpcbBuffer指定的緩衝區大小不夠大,沒法接收字段數據。此時函數返回時,參數lpcbBuffer將包含用於讀取字段數據的正確緩衝區大小。
n ERROR_INVALID_HANDLE:表明非法的數據庫句柄,參數hDbase爲NULL或INVALID_HANDLE_VALUE。
n ERROR_INVALID_PARAMETER:表明下面三個參數至少其中一個被設置爲NULL: lpcPropID, lplpBuffer,lpcbBuffer。
n ERROR_KEY_DELETED:表明當前記錄已經被刪除
n ERROR_NO_DATA:表明記錄不包含指定的請求字段。
n ERROR_NO_MORE_ITEMS:表明數據庫指針當前不指向任何一個記錄,須要首先定位記錄
n ERROR_NOT_ENOUGH_MEMORY:表明內存分配失敗。
n 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,可能的錯誤碼爲:
n ERROR_INVALID_HANDLE:參數hDatabase被設置爲NULL或INVALID_HANDLE_VALUE。
n ERROR_INVALID_PARAMETER:參數oidRecord被設置爲NULL或非法值
n ERROR_NOT_FOUND:參數oidRecord指定的記錄不存在。
n 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類型。
l 參數dwMode指定流對象的訪問權限,可取如下兩種值:
n GENERIC_READ: 對流對象提供只讀訪問權限,不容許寫入。
n 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指定移動的起始參考位置,可取值爲:
n STREAM_SEEK_CUR: 以當前指針位置做爲起始參考位置。這時,參數cbMove做爲有符號數,正數表示向前(向末尾位置方向)移動,而負數表示向後(向開始位置方向)移動。
n STREAM_SEEK_END: 以流對象的末尾位置爲起始參考位置,向前移動。
n STREAM_SEEK_SET: 以流對象的起始位置爲起始參考位置,向後移動。
l 參數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種:
n CEDB_ISOLEVEL_DEFAULT或者CEDB_ISOLEVEL_READCOMMITTED:當前事務正在進行更改的數據不容許其它事務讀取,直到事務提交完成。
n CEDB_ISOLEVEL_REPEATABLEREAD:當前事務正在進行更改的數據容許其它事務讀取,可是不容許其它事務更改。
n 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,包括掛載及卸載數據庫卷,枚舉數據庫卷和數據庫,查詢對象信息,回寫數據庫卷,建立刪除數據庫。建立會話,查找記錄,讀寫數據庫內的記錄,使用流讀寫記錄,以及怎麼使用事務操做。