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

相关文章
相关标签/搜索