现在的位置: 首页 > 综合 > 正文

EDB的排序和读取教程

2013年10月06日 ⁄ 综合 ⁄ 共 3643字 ⁄ 字号 评论关闭

 

------------------------------------------------------
1. EDB数据库的结构
------------------------------------------------------
    EDB数据库的基本单位是Volume,也就是卷,通常存在于一个磁盘文件中,例如:pim.vol等等。

    在卷中包含若干数据库,可以由数据库名称或者OID(对象编号)来访问他们,例如:pim.vol中包含名为“Appointments Database”的数据库,其OID为1077960704。

    而每个数据库包含很多记录,可以通过OID或者在数据库中的排序标号来访问每个记录。

    每个记录又包含很多属性,记录属性==记录数据。记录的属性由CEPROPVAL类型的结构来存储,每个记录存储一个CEPROPVAL类型的数组,数组大小就是属性数量。
    每个记录的属性由CEPROPVAL::propid来标识。propid是一个双字类型(DWORD)的数据,高位字定义的是属性名称ID,低位字代表数据库中记录的属性数据的类型,如:LPWSTR,UI4等等。其中PIM.VOL中的属性ID定义在"pimstore.h"中。
    属性的数据则存储在CEVALUNION类型的联合(union)中,CEVALUNION的定义如下:
    typedef union _CEVALUNION {
    short           iVal;     //@field CEVT_I2
    USHORT          uiVal;    //@field CEVT_UI2
    long            lVal;     //@field CEVT_I4
    ULONG           ulVal;    //@field CEVT_UI4
                              //@field CEVT_AUTO_I4_
    FILETIME        filetime; //@field CEVT_FILETIME
    LPWSTR          lpwstr;   //@field CEVT_LPWSTR - Ptr to null terminated string
    CEBLOB          blob;     //@field CEVT_BLOB - DWORD count, and Ptr to bytes
                              //@field CEVT_AUTO_I8
                              //@field CEVT_RECID
                              //@field CEVT_STREAM
    BOOL            boolVal;  //@field CEVT_BOOL
    double          dblVal;   //@field CEVT_R8
} CEVALUNION, *PCEVALUNION;

【总结】实际上,数据库就是一个表,表中各行就是记录,每个记录存储很多不同类型的数据,比如:在记录OID=234里面,存储了小王(姓名)、男(性别)、安徽(籍贯)...。表最顶上的一行,也就是表头,存储的就是属性的propid,代表属性类型,例如:创建数据库时,可以指定姓名的PropID=0x0012001f,性别的PropID=0x0013001f等等。将来打开数据库时,可以根据表头,也就是propid来访问想要的属性,也可以根据propid指定排序的规则,例如:是依据姓名(0x0012001f)排序还是依据籍贯(0x0013001f)排序。

------------------------------------------------------
2. 如何读取数据库
------------------------------------------------------
Step 1: 要载入数据库所在的卷(Volume)
    调用CeMountDBVolEx()载入指定的数据库文件,并且得到数据库文件的GUID,例如:CEGUID m_sDBGuid。

Step2: 创建数据库会话

    调用CeCreateSession(m_sDBGuid),由此得到会话的句柄HANDEL se;

Step3:打开卷中想要访问的数据库

    调用CeOpenDatabaseInSession()打开数据库。

    可以设定该函数的形参“SORTORDERSPECEX* pSort”指定排序规则。以后在调用CeSeekDatabaseEx()移动记录指针并访问数据库时,将遵循此规则。

    必须注意的是,pSort结构的访问规则必须在数据库的访问规则中存在,也就是说,pSort指向的结构中,wNumProps、wKeyFlags、rgPropID[]数组中的propid必须和数据库属性中存储的某一个排序规则保持严格一致【注:数据库在创建时,会指定一个CEDBASEINFOEX类型的结构,该结构中,CEDBASEINFOEX::rgSortSpecs[16]指定的是SORTORDERSPECEX类型的数组,也就是说,数据库可以有最多16种排序规则,这些规则存储于数据库中】。在打开数据库时,只需要选择其中一种排序规则,且排序规则必须和创建数据库时保持一致,不能出现数据库中没有的propid。并且对于EDB而言,SORTORDERSPECEX::wVersion必须等于2!如果这些准则没有满足,则CeOpenDatabaseInSession()函数返回INVALID_HANDLE_VALUE。

Step4:读取数据库记录

    数据库中有一个记录指针,CeReadRecordPropsEx()函数读取的就是记录指针处的记录属性。要使记录指针指向想要访问的记录,也就是调用CeSeekDatabaseEx()函数搜索数据库的记录集,并使记录指针指向搜索结果,可以有很多种搜索方法,例如:输入CEDB_SEEK_CEOID,根据指定的OID搜索,输入CEDB_SEEK_BEGINNING,从数据库第一个元素搜索位于偏移量为dwValue的记录。

    CeReadRecordPropsEx()将返回记录属性数组的头指针,如前所述,该数组是CEPROPVAL类型,我们根据propid确定属性的数据类型,再从CEVALUNION类型的数据读取属性值。

    具体而言,采用CeReadRecordPropsEx()函数读取属性时,该函数的形参“lplpBuffer”返回的是CEPROPVAL类型的数组的头指针,rgPropID[]存储的是要读取的属性的PropID,也就是指定客户需要读取那些属性,由于客户一次可能读取很多属性,所以rgPropID[]是个数组,而形参lpcPropID则指定用户需要读取的属性数目,当lpcPropID=0时,代表读取该记录的全部属性,lpcPropID在CeReadRecordPropsEx()函数返回时被赋值,代表读取的属性数量。

------------------------------------------------------
3. 如何列举并读取数据库属性
------------------------------------------------------

   如前所述,一个卷包含若干数据库,我们可以枚举各个数据库,并且读取他们的属性。

Step 1:载入数据卷

    调用CeMountDBVolEx()函数。

Step 2: 得到枚举环境句柄

    调用CeFindFirstDatabaseEx()函数,得到一个句柄,该句柄作为CeFindNextDatabaseEx()函数的输入,构成枚举环境。

Step 3: 枚举数据库

    调用CeFindNextDatabaseEx()函数枚举数据库,移动数据库指针,并且得到当前数据库的OID。枚举时采用while(){}循环,循环中断依据就是数据库oid==0。例如:
    while((oid=CeFindNextDatabaseEx(se,0))!=0)
    {
       //TODO: Add your code here:
    };

Step 4: 读取数据库信息

    调用CeOidGetInfoEx2()函数,依据oid读取数据库信息。其实该函数可以根据oid得到数据库、文件、路径和记录等很多种对象的信息。在调用该函数时,可能出现调用堆栈被清空的问题,这是数组越界所致,是没有#define EDB造成的。
    数据库的属性存储在CEOIDINFOEX::infDatabase成员中,该成员是CEDBASEINFOEX类型,其详细的含义见MSDN。

抱歉!评论已关闭.