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,包括挂载及卸载数据库卷,枚举数据库卷和数据库,查询对象信息,回写数据库卷,建立删除数据库。建立会话,查找记录,读写数据库内的记录,使用流读写记录,以及怎么使用事务操做。