windows CE 学习之属性数据库

开始使用 Windows CE ,最近学习了一下其自带的属性数据库,天天翻 MSDN 太麻烦了,整理总结一下,以备以后使用时方便查询。

Windows CE 属性数据库有 CEDB 和 EDB 两种,其中前者是早期的版本,后者随 WINCE 5.0 发布。 EDB 与 CEDB 相比具备事务的功能,同时支持更多的更全的索引,支持更多的属性数量和更好的性能,特别是存储较大数据时。

虽然 WINCE 5.0 支持 EDB ,但是发布的 Windows  CE Standard SDK 5.0 中却不含有 EDB 的 API , Windows mobile 的对应版本中则含有。在 WINCE 5.0 中使用 EDB 需要自己编译 SDK 来实现。

下面讨论一下 CEDB API 的使用。

根据 MSDN 的说明, CEDB 的 API 有些已经废弃,主要整理一下我已经学习使用的几个 API 的使用方法。

首先明确几个基本的概念:

数据库卷 (Database Volume) :一个文件,数据库中的所有数据存放的地方,可以含有多个数据库,每个数据库卷需要挂载才能使用(系统的对象存储器不在本文讨论之列),使用系统唯一的 GUID(Global Unique ID entifier ) 标示;

数据库 (DataBase) :数据库,数据的最高逻辑组织单元,多个数据库可以存放在同一个数据库卷中,彼此之间使用对象标示符 (OID : Object ID) 标示;

属性 (Property) :存储数据的逻辑性质 ( 结构化数据中的一项 ) ;

属性 ID :属性 ID 有两个功能,确定数据的类型和同类型的数据区分,关于属性 ID 需要说明的是 CEDB 支持 9 中类型的数据,包括二进制大对象( BLOB )、布尔型、 FILETIME 型、 2 字节 4 字节的有符号和无符号整数, 8 字节整数和 Unicode 字符串类型,属性 ID 用一个 4 字节的整数 ( 内存块 ) 表示,其中低字存放属性数据类型,有系统预定义了,高字存放应用程序自定义的属性标示符,用以区分同类型的属性,这样就使用属性 ID 完成了定义数据类型和属性性质的功能 ;

CEDB 的这些概念与关系型数据库对比就是:数据库卷相当于关系型数据库中的数据库, CEDB 的数据库相当于关系型数据库中的表,而 CEDB 中的属性则相当于关系型数据库中的字段。

1、          挂载数据库卷

数据库卷是 CEDB 存储数据的物理所在,是一个普通的文件,如果没有特别的属性标注,可能会被随意删除。同使用文件一样,在使用前需要先打开文件,这里称为数据库卷的挂载。

BOOL CeMountDBVol( PCEGUID pceguid, LPWSTR lpszDBVol,

  DWORD dwFlags);

pceguid : CEGUID 类型指针,传入 CEGUID 变量,成功返回系统内唯一标示本数据库卷的 CEGUID ;

lpszDBVol : Unicode 字符串,传入数据库卷文件的路径;

dwFlags : DWORD 型数据,标示数据库卷的挂在类型,一般使用 OPEN_ALWAYS 即可;

函数成功返回 true ,失败返回 false ,可用 GetLastError 函数查看错误码。

2、          卸载数据库卷

关闭数据库卷文件。

BOOL CeUnmountDBVol(  PCEGUID pceguid);

函数参数即待卸载的数据库卷 GUID 地址,成功执行返回 true ,失败返回 false 。

3、          创建数据库

数据库卷挂载成功之后,在存储数据之前,其中必须有数据库用于组织数据,数据库的创建使用函数:

CEOID CeCreateDatabaseEx2( PCEGUID pguid, CEDBASEINFOEX* pInfo);

pguid :所在数据库卷的 GUID 地址;
pInfo :数据库基本信息,主要包括属性和索引信息;

CEDBASEINFOEX 结构含有 9 个字段:

wVersion :版本信息, CEDB 只能使用 1 ;

dwFlags :标志信息,由于 CEDBASEINFOEX 结构可能用于不同的函数之中,数据库的创建、获取或设置数据库的信息等,用这一标志用于表示传入函数的 CEDBASEINFOEX 结构中那些字段是有效字段。创建函数基本上使用 CEDB_VALIDNAME| CEDB_VALIDTYPE |CEDB_VALIDSORTSPEC 组合就足够了,标示后的字段必须赋值,以免操作失败;

szDbaseName :数据库名, Unicode 字符串,由于 WINCE 中全部使用宽字符,此后的字符串若非特别说明全部都是宽字符型的,需要用 CEDB_VALIDNAME 标志标示;

dwDbaseType :数据库的类型标示符,随机的一个整数就行了,暂时没有搞清楚用途,一般填 1985 ,需要用 CEDB_VALIDTYPE 标志标示;

dwNumRecords :数据库中记录的个数;

wNumSortOrder :数据库中索引的个数;

dwSize :数据库的大小,使用 byte 衡量;

ftLastModified :数据库最近一次的修改时间, EDB 已经废弃这一字段,不用为上;

rgSortSpecs :数据库的索引信息,使用 CEDB_VALIDSORTSPEC 标志标示,本字段是一个容量为 CEDB_MAXSORTORDER 的 SORTORDERSPECEX 类型数组,其中只有前 wNumSortOrder 个有效。

至于 SORTORDERSPECEX 数据类型,是一个记录索引信息的结构体,含有 5 个字段:

wVersion :版本信息, CEDB 只能填 1 ;

wNumProps :本索引中属性的数量;

wKeyFlags :标示索引的属性,是否要求唯一性;

rgPropID :索引含有的属性信息,容量为 CEDB_MAXSORTPROP 的 CEPROPID 数组,同样,其中有效的是前 wNumProps 个,索引中属性的重要性,即后续排序所依据的属性,根据属性在本数组中的位置决定,排在前面的属性优先排序;

rgdwFlags :索引排序的方式,是与 rePropID 对应的数组,对应的位置决定对应的属性的排序方式,如升序或降序等,使用默认值就行。需要注意的是当索引是由多个属性键组合而成的时候,必须明确指定每个属性键的排序方式,否则会出现参数不合法的错误(87),从而导致函数调用失败。

4、         打开数据库

数据库卷挂载之后,在使用数据库之前需要先打开数据库,CEDB使用CeOpenDatabaseEx2函数打开数据库。

HANDLE CeOpenDatabaseEx2( PCEGUID pguid, PCEOID poid,

  LPWSTR lpszName, SORTORDERSPECEX* psort,

DWORD dwFlags,CENOTIFYREQUEST*pRequest);

pguid:数据库卷GUID;

poid:数据库的对象ID,数据库卷内唯一,即通过其数据库卷的ID和数据库本身的ID就可以系统内唯一确定数据库了;打开数据库的方式可以使用对象ID的方式,也可以使用数据库名的方式,如果使用对象ID的方式,则此处需要填写对象的ID,如果使用数据库名的方式打开,传入的参数必须初始化为0,函数成功返回后,将通过本参数传回数据库的对象ID;

lpszName:数据库名,Unicode字符串,注意,如果传入的对象ID不为0,则本参数将被忽略;

psort:索引信息,打开的数据库将按何种方式排序,这将影响后续的顺序访问操作和随机访问函数CeSeekDatabaseEx的行为,注意,此处的索引不一定必须是创建时指定的索引,但是索引中的属性信息必须同数据库内的属性相同;

dwFlags:当前指针的行动标志,可以是CEDB_AUTOINCREMENT或0,前者将在使用读函数CeReadRecordPropsEx操作数据库之后,操作指针自动前移,这样下次读取时就会读取下一条记录;0则表示操作指针不会自动前移,除非使用随机访问函数CeSeekDatabaseEx;

pRequest:注册信息,接受关于数据库的更改信息,由于CEDB不支持多用户,此处很少用,待学习;

返回值:数据库句柄,使用完成后需要使用Closehandle函数关闭。INVALID_HANDLE_VALUE表示打开数据库失败。

5、         关闭数据库

关闭数据库使用CloseHandle函数关闭打开数据库时获取的句柄即可。

6、         删除数据库

使用CeDeleteDatabaseEx函数删除数据库。

BOOL CeDeleteDatabaseEx( PCEGUID pguid, CEOID oid);

pguid:数据库卷GUID;

oid:数据库对象ID;

注意:删除数据库前必须先关闭数据库。

7、         添加或编辑记录

使用CeWriteRecordProps函数向已经打开的数据库中写入记录。

CEOID CeWriteRecordProps(HANDLE hDbase, CEOID oidRecord,

  WORD cPropID, CEPROPVAL* rgPropVal);

hDbase:数据库句柄,打开数据库函数的返回值;

oidRecord:记录的对象ID,记录的OID在数据库卷内唯一,用以表示每一条记录,如果传入函数的值为0,则表示是新添加一条记录,否则表示对OID为oidRecord记录的更新;

cPropID:记录中属性的数量;

rgPropVal:传入函数的记录具体值,是CEPROPVAL类型的指针,有效的属性数量是数组的前cPropID个。

返回值:0表示失败,返回被操作的记录OID表示成功。

8、         记录的读取

使用CeReadRecordPropsEx函数顺序的从数据库中读取记录。

CEOID CeReadRecordPropsEx( HANDLE hDbase, DWORD dwFlags,

  LPWORD lpcPropID, CEPROPID* rgPropID, LPBYTE* lplpBuffer,

  LPDWORD lpcbBuffer,  HANDLE hHeap);

hDbase:数据库句柄,CeOpenDatabaseEx2函数的返回值;

dwFlags:返回值内存的处理方案标志,0表示全部由调用方负责分配储存返回信息的内存,如果传入的内存过小,则函数调用失败;CEDB_ALLOWREALLOC表示当调用方分配的函数不够时,本函数将使用LocalAlloc函数为返回信息重新分配足够的内存,需要注意的是,这些内存在使用完后需要使用LocalFree函数释放掉;

lpcPropID:指定需要读取的属性数量,如果为null,则表示返回所有的属性;

rgPropID:CEPROPID类型指针,指定需要返回的属性,如果为null,表示返回所有的属性;如果指定,则前lpcPropID个属性有效;

lplpBuffer:指向存储返回信息的内存,调用时通常将dwFlags函数置为ALLOWREALLOC,将本参数置null,由本函数负责分配内存,调用方使用完后释放;

lpcbBuffer:返回实际存储在lplpBuffer所指向的内存中返回信息的字节数,如果本函数为返回信息分配了内存,则本参数可以用来计算重新分配的内存大小(即本值减去传入内存的大小)

hHeap:指向应用程序堆,ALLOWREALLOC被设置有效,一般设置为NULL即可。

返回值:读取记录的OID表示成功,0表示失败。

9、         记录随机读取

使用CeSeekDatabaseEx函数可以实现对数据库的随机读取。函数CeReadRecordPropsEx只能向前移动,不能向后访问。

CEOID CeSeekDatabaseEx(HANDLEhDatabase,

  DWORD dwSeekType, DWORD dwValue, WORD wNumVals,

  LPDWORD lpdwIndex);

hDatabase:数据库句柄,CeOpenDatabaseEx2函数返回值;

dwSeekType:操作指针移动类型,CEDB中有8中移动方式:

CEDB_SEEK_CEOID:查找指定OID的记录,dwValue将传入这一OID,这是最有效的查找方式;

CEDB_SEEK_VALUESMALLER:向后查找指定的记录,查找与指定记录最接近的值,即在升序排列中,找出所有小于等于指定值的最大值,在降序排列中,找出所有大于等于指定值的最小值,记录的信息存放在dwValue中,以CEPROPVAL属性组的方式传入,wNumVals是属性组的有效属性个数;如果当前操作指针之前没有符合的记录,则返回失败,操作指针停留的数据库的开始处。

CEDB_SEEK_VALUEFIRSTEQUAL:从开始处开始查找,直到找到第一个指定的记录,记录值的传入方式同上所述,当找不到指定值时,操作指针停留在数据库的尾部;

CEDB_SEEK_VALUENEXTEQUAL:从当前位置开始查找指定的值,记录值的传入方式同上所述,操作失败则操作指针停留在数据库的尾部,与CEDB_SEEK_VALUEFIRSTEQUAL配合使用可以找出数据库中所有与指定值相同的记录;

CEDB_SEEK_VALUEGREATER:向前查找指定的记录,其他的与CEDB_SEEK_VALUESMALLER类似;

CEDB_SEEK_BEGINNING:查找距开始位置dwValue距离的位置,dwValue必须为正;

CEDB_SEEK_CURRENT:查找距当前位置dwValue距离的位置,dwValue为正则顺序查找,为负则逆向查找;

CEDB_SEEK_END:查找距结束位置dwValue距离的位置,dwValue必须为负;这与EDB中有所差别,EDB中必须为正。

dwValue:DWORD类型,根据dwSeekType决定数据类型,传入函数需要的相关信息。可能是CEOID、DWORD计数器或一个CEPROPVAL指针;

wNunValue:WORD类型,CEPROPVAL数据的个数,只有在dwSeekType为CEDB_SEEK_VALUESMALLER, CEDB_SEEK_VALUEGREATER, CEDB_SEEK_VALUEFIRSTEQUAL时有效;

lpdwIndex:LPDWORD类型,当前位置距数据库开始位置的距离,该参数可以为NULL,否则会减低查找的性能,应该尽量避免使用该参数。

返回值:CEOID类型,当前记录的OID,0表示操作失败。

10、         删除记录

使用函数CeDeleteRecord删除数据库中的记录。

BOOL CeDeleteRecord(HANDLE hDatabase, CEOID oidRecord);

hDatabase:HANDLE类型,待删除记录所在数据库的句柄,可以使用CeOpenDatabaseEx2函数获得该句柄;

oidRecord:CEOID类型,待删除记录的ID,可以使用CeWriteRecordProps函数获得;

返回值:BOOL类型,TURE标示成功删除,false标示失败;

备注:如果打开数据库时,设置了CEDB_AUTOINCREAMENT标记,删除操作成功执行后,数据库读取指针会自动下移一位;如果没有设置该标记,则使用相同数据库句柄的下一个读操作将失败,即数据库读取指针未能更新,从而失效。

11、         获取对象信息

使用函数CeOidGetInfoEx2获取对象信息。

BOOL CeOidGetInfoEx2( PCEGUID pceguid, CEOID oid,

  CEOIDINFOEX* poidInfo);

pceguid:PCEGUID类型,待操作数据库卷的GUID;

oid:CEOID类型,待操作对象的OID;

poidInfo:CEOIDINFOEX类型指针,指向存储返回信息的结构。

返回值:BOOL类型,TRUE表示成功,FALSE表示失败。

12、         通过句柄获取数据库信息

使用函数CeGetDBInformationByHandle获取数据库基本信息。

BOOL CeGetDBInformationByHandle(HANDLE hDbase,

  LPBY_HANDLE_DB_INFORMATION lpDBInfo );

hDbase:HANDLE类型,待操作数据库的句柄;

lpDBInfo:LPBY_HANDLE_DB_INFORMATION类型,指向存储返回信息的结构,需要注意的是,其wVersion字段需要初始化为BY_HANDLE_DB_INFORMATION_VERSION,即1。否则可能会出现无效参数的错误。

返回值:

BOOL类型,非0为成功,0为失败;

13、      刷新数据库卷

使用函数CeFlushDBVol将缓冲区中的数据写入到永久存储区域。

BOOL CeFlushDBVol( PCEGUID pceguid);

pceguid:PCEGUID类型,指向待操作的数据库卷GUID,数据库卷必须已经挂载;当为NULL时,系统中所有已挂载的数据库卷将被操作。

返回值:BOOL类型,TRUE表示成功,FALSE表示失败。

备注:对于已经挂载的数据库卷,其所有的操作都会现在缓存中操作。只有系统周期到达、数据满、数据库卷卸载时会自动将缓存中的数据写入永久存储器。否则只有使用本函数显示的刷新缓存。系统重启或掉电,缓存中的数据将丢失。

14、      遍历数据库卷中的数据库

组合使用函数CeFindFirstDatabaseEx和函数CeFindNextDatabaseEx可以遍历数据库卷中所有的数据库信息。

HANDLE CeFindFirstDatabaseEx( PCEGUID pceguid,

  DWORD dwDbaseType);

pceguid:PCEGUID类型指针,指定待操作的数据库卷;如果该参数设为NULL或指向无效GUID,则遍历所有的已挂载数据库卷;

dwDbaseType:DWORD类型,需要遍历的数据库类型,如果设为0,则遍历数据库卷中所有的数据库;

返回值:能够操作获取信息的句柄,如果返回的句柄为INVALD_HANDLE_VALUE则表示操作失败。

注意:本函数并不能直接获取数据库的信息,而是返回能够操作这些信息的句柄,具体的信息可以通过CeFindNextDatabaseEx函数操作句柄来获取。需要注意的是,操作完成后,必须使用CloseHandle关闭本函数返回的句柄,从而释放本函数为存放数据库信息而分配的内存。

可以使用宏CREATE_SYSTEMGUID和宏CREATE_INVALID来分别获取系统的GUID或无效的GUID。

CEOID CeFindNextDatabaseEx( HANDLE hEnum,

  PCEGUID pceguid);

hEnum:HANDLE类型,自CeFindDatabaseEx函数返回的操作数据库基本信息的句柄。

pceguid:PCEGUID类型,返回对应数据库所在的数据库卷的GUID;

返回值:CEOID类型,数据库的OID。0表示操作失败。

备注:通过返回值和参数pceguid带回的GUID可以唯一标示数据库。

遍历所有的数据库,只需不断调用本函数即可,当返回值为0,错误信息为ERROR_NO_MORE_ITEMS时,遍历完所有的数据库。如果在遍历期间,数据库被删除,则会操作失败,并获得ERROR_KEY_DELETED的错误,此时,如果需要继续遍历,则必须从头开始,先调用CeFindFirstDatabaseEx函数,然会调用本函数。注意,遍历结束后,必须使用CloseHandle函数关闭操作句柄,释放相关内存。

15、      列举数据库卷

使用函数CeEnumDBVolumes遍历系统中所有已挂载数据库卷。

BOOL CeEnumDBVolumes( PCEGUID pceguid,

  LPWSTR lpBuf,DWORDdwNumChars);

pceguid:PCEGIUD类型指针,第一次调用时使用CREATE_INVALIDGUID初始化CEGUID类型变量,之后使用上一次调用获取的值;

lpBuf:LPWSTR类型,用于返回当前获取的数据库卷的名字;

dwNumChars:DWORD类型,指定lpBuf的长度,防止溢出,以字节度量;

返回值:BOOL类型,TURE标示成功,FALSE标示失败。

备注:通过不断的调用本函数可以遍历系统中已经挂载的所有数据库卷信息。首先使用CREATE_INVALIDGUID初始化的CEGUID类型变量标示遍历开始,成功操作后,系统将第一个已挂载的数据库卷ID和名字分别填在pceguid参数和lpBuf中返回。后续的操作使用前一次调用返回的数据库卷ID做pceguid参数,从而遍历系统中所有已经挂载的数据库卷。当函数操作失败,错误信息是ERROR_NO_MORE_ITEMS时,表示遍历完成。如果错误信息是ERROE_INSUFFICIENT_BUFFER时,表示缓冲区不够,重新开辟缓冲区后,继续调用本函数,使用失败调用返回的CEGUID变量值重新获取失败的值,从而避免从头开始遍历。

16、      剩余函数

CeChangeDatabaseLCID

CeFreeNotification

CeSetDatabaseInfoEx2

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值