`
qlc29qlc
  • 浏览: 12561 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

Windows Mobile 平台EDB 数据库的应用与开发

 
阅读更多

Windows Mobile 平台EDB 数据库的应用与开发
2011年04月26日
  Windows Mobile 平台EDB 数据库的应用与开发
  程乐乎 1,邹仕洪1,林宇 2,史文勇2
  1.北京邮电大学网络技术研究院,北京(100876)
  2.北京网秦天下科技有限公司,北京(100013)
  E-Mail: clh213@gmail.com
  摘要:本文阐述了Windows Mobile 平台下EDB 数据库的基本知识和常用的操作函数及数据结构体,在此基础上结合Mobile 系统自身的联系人(contacts)数据库实例,系统介绍了EDB 数据库的创建思路和具体操作,如读取记录、添加记录、删除和查询记录等。另外还深入介绍了EDB 的事务操作和监控EDB 数据库变化的通知机制。
  关键词:智能手机,Windows Mobile,EDB,系统联系人
  1. 引言
  近年来,随着人们对移动办公和娱乐需求的不断提高,传统的以通讯功能为主的手机已经不能适应人们的需求。正是在这种情况下,类似当前PC 的具备通用操作系统的智能手机也就应运而生,这些智能手机的一大特点便是其操作系统不再是各个厂家根据自己的硬件产
  品专门定制,而是采用类似PC 上的Windows 操作系统一样通用的操作系统,该系统的接口对外公开,可以由第三方开发者开发该系统应用,这样配合手机硬件水平的不断提高,使得手机的应用领域大大拓展。随着软硬件性能的提升,智能手机已经不仅仅是一个手机通讯工具,而成为了用户的个人数据和移动办公中心。基于智能手机平台的应用,需要处理大量的用户个人数据和应用数据,因此必需提供数据存储、数据管理和查询的功能,同时对于数据的安全性和完整性也必须提供支持。此外,智能手机设备还可以作为后台信息系统的信息收集、处理和接收终端[1]。
  2. 背景
  2.1. 智能手机简介
  目前市场上出现的智能手机操作系统主要为 Symbian、Windows Mobile、Palm OS 以及Linux 等几种。Windows Mobile(以下简称WM)是在Windows CE 系统基础上为智能移动终端设备设计的操作系统。基于WM 操作系统的智能终端设备分为Smartphone 和Pocket PC 两个大类。其中Smartphone 从外观设计、使用习惯方面来看,其更像一部电话,同时具备一定的数据管理和处理能力。而Pocket PC 的功能更类似于一部个人电脑,有非常强大的数据管理和处理功能,同时Pocket PC 也加入了电话功能,使其成为新的Pocket PC phone[2] 。
  2.2. EDB 数据库简介
  WM 5.0 以前的系统使用的是CEDB 数据库,EDB 是WM 5.0 中的新特性之一。为了改善应用程序的性能和长期可移植性,CEDB 已经被 EDB 所取代。EDB 是一个基于SQL Server CE 的嵌入式数据库引擎,为基于Windows CE 的应用程序提供核心功能。通过使用EDB,开发者能够创建一个对象存储,称为数据库卷(volume),其中可以包含多个数据库。该数据库卷是基于文件的,因此可以很容易被复制和移动[3]。
  EDB 作为CEDB 的更新和增强版本,还支持 事务(transaction) 多用户同时访问
  支持 stream 类型的数据 多种排序方式,多个主属性
  增强的性能,尤其是较大的数据库
  3. EDB 数据库设计
  在 WM 系统中,系统联系人和SIM 卡联系人数据,是以EDB 形式存储的。因此本文结合WM 系统联系人数据库的实际例子,详细介绍EDB 数据库的设计与应用开发。
  3.1. EDB 基本概念
  Volume(数据库卷):用来存储数据库的文件,一个volume 上可以创建多个数据库。例如WM 系统的"\\pim.vol",是用来存储个人信息的卷文件,里面有系统联系人、通话记录、任务、约会等多个数据库。 Database(数据库):每个数据库即一个表。数据库存储在volume 文件内。其中,WM系统的"\\pim.vol"卷文件中,联系人数据库的名字为"Contacts Database"。 Property ID(属性ID):每个数据库包含多个属性,即表的多个字段。属性ID 不仅代表该属性的名字,同时也指定了该属性的数据存储类型(int、string、time……)。 CEOID(对象ID):DWORD 类型,用来代表一个数据库或者数据库中每条记录的唯
  一ID 标识。可以理解为数据库中每条记录存放的位置或者索引。 CEGUID:Globally Unique Identifier(全球唯一标识符),它是一个128 比特(16 字节)的结构。用来标识一个被加载的数据库卷。CEGUID 和CEOID 一起,唯一标识一条记录,或者唯一标识一个数据库。
  EDB 数据库的常用操作步骤为:首先加载一个数据库卷文件,然后打开卷文件中的某个数据库,获取数据库的句柄。此后通过这个打开的数据库句柄,对数据库中的记录进行读写、删除、更新、查找的操作。最后关闭数据库,卸载之前加载的卷文件,结束操作[4]。
  3.2. EDB 常用操作函数
  EDB 提供了丰富的操作API,来支持各种数据库应用。下面列举出一些最常用的API,读者可以通过WM SDK 帮助文档或者MSDN,详细了解这些API 的参数说明和注意事项,同时可以获取更多的EDB 相关API[5]。
  加载或者创建一个数据库卷文件
  BOOL CeMountDBVolEx(PCEGUID pGuid, LPWSTR lpwszDBVol,
  CEVOLUMEOPTIONS* pOptions, DWORD dwFlags );
  卸载数据库卷文件
  BOOL CeUnmountDBVol( PCEGUID pGuid);
  打开一个数据库
  HANDLE CeOpenDatabaseInSession(HANDLE hSession, PCEGUID pGuid, PCEOID poid,
  LPWSTR lpwszName, CESORTORDERSPEC* pSort, DWORD dwFlags,
  CENOTIFYREQUEST* pRequest);
  新建一个数据库
  CEOID CeCreateDatabaseWithProps( PCEGUID pGuid, CEDBASEINFOEX* pInfo,
  DWORD cProps, CEPROPSPEC* prgProps);
  创建或者更新一条数据记录
  CEOID CeWriteRecordProps( HANDLE hDatabase, CEOID oidRecord,
  WORD cPropID, CEPROPVAL* prgPropVal );
  读取一条数据记录
  CEOID CeReadRecordPropsEx( HANDLE hDatabase, DWORD dwFlags, LPWORD
  lpcPropID, CEPROPID* prgPropID, LPBYTE lplpBuffer, LPDWORD
  lpcbBuffer, HANDLE hHeap);
  查找一条记录
  CEOID CeSeekDatabaseEx(HANDLE hDatabase, DWORD dwSeekType, DWORD
  dwValue, WORD wNumVals, LPDWORD lpdwIndex);
  删除一条记录
  BOOL CeDeleteRecord( HANDLE hDatabase, CEOID oidRecord );
  创建一个 session。一个session 用来开始、提交、回滚事务。
  HANDLE CeCreateSession( CEGUID* pGuid );
  开始一个事务
  BOOL CeBeginTransaction( HANDLE hSession, CEISOLATIONLEVEL isoLevel); 提交一个事务
  BOOL CeEndTransaction( HANDLE hSession, BOOL fCommit);
  3.3. 创建和打开数据库
  3.3.1. 打开系统联系人数据库
  第一步,首先加载WM 系统联系人数据库所在的卷文件"\\pim.vol",得到该卷文件的CEGUID。调用方式如下:
  CEGUID g_ceGuidInitDB; // 存储加载的卷文件"\\pim.vol"的GUID
  if(FALSE == CeMountDBVolEx(&g_ceGuidInitDB, L"\\pim.vol", 0, OPEN_ALWAYS ))
  {
  DWORD error = GetLastError();
  }
  如果是需要创建一个新的卷文件,只要把第四个dwFlags 参数设为CREATE_NEW 或者
  CREATE_ALWAYS,然后指定卷文件的绝对路径名就可以了。
  第二步,打开系统联系人数据库"Contacts Database"
  HANDLE g_hContactDB; // 数据库句柄
  CEOID oidContact = 0; // 数据库的CEOID
  g_hContactsDB = CeOpenDatabaseInSession(NULL, &g_ceGuidInitDB, &oidContact,
  L"Contacts DataBase", NULL, CEDB_AUTOINCREMENT, NULL);
  if( INVALID_HANDLE_VALUE == g_hContactDB )
  {
  DWORD error = GetLastError();
  }
  其中, 第六个参数为CEDB_AUTOINCREMENT 标志, 指示每调用一次
  CeReadRecordPropsEx 读取记录,数据库中的当前指针位置会自动增加到下一条记录。也可以把该参数设为0。
  如果成功打开了联系人数据库,返回数据库句柄g_hContactsDB,并且得到的oidContact值为数据库的CEOID。
  3.3.2. 创建新的数据库
  假设某个特定应用,需要对系统联系人进行分组,分组包括"亲人"、"同学"、"朋友"、"商务"等等。则需要创建一个新数据库"ContactsGroupDB",用来存储每个联系人的姓名、电话号码、所属分组。创建该数据库步骤如下:
  第一步,定义各个属性的 PropID
  const CEPROPID GroupIDPropid = MAKELONG(CEVT_UI4, 0); // 分组ID,无符号整型
  const CEPROPID NamePropid = MAKELONG(CEVT_LPWSTR,1); // 姓名,string 类型
  const CEPROPID PhoneNumberPropid = MAKELONG(CEVT_LPWSTR,2); // 电话号码,string
  第二步,填充数据库信息结构CEDBASEINFOEX 和数据库属性结构CEPROPSPEC
  DWORD wProps = 3; // 数据库有三个属性
  CEPROPSPEC propSpec[3];
  memset(propSpec,0,sizeof(CEPROPSPEC)*wProps);
  propSpec[0].wVersion = 1;
  propSpec[0].propid = GroupIDPropid;
  propSpec[0].dwFlags = DB_PROP_NOTNULL; // 分组ID,不能为空
  propSpec[1].wVersion = 1;
  propSpec[1].propid = NamePropid; // 联系人名字,可以为空
  propSpec[2].wVersion = 1;
  propSpec[2].propid = PhonePropid;
  propSpec[2].dwFlags = DB_PROP_NOTNULL; // 联系人号码,不能为空
  // 填充数据库信息结构
  CEDBASEINFOEX ced;
  memset(&ced, 0, sizeof(CEDBASEINFOEX));
  ced.wVersion = CEDBASEINFOEX_VERSION;
  ced.dwSize = sizeof(CEDBASEINFOEX);
  ced.dwFlags = CEDB_VALIDNAME | CEDB_VALIDSORTSPEC;
  // CEDB_VALIDNAME 数据库的名字有效
  // CEDB_VALIDSORTSPEC 数据库排序有效
  wcsncpy(ced.szDbaseName, L"ContactsGroupDB", CEDB_MAXDBASENAMELEN);
  第三步,在上节加载的"\\pim.vol"卷上新建"ContactsGroupDB"数据库
  CEOID oid = CeCreateDatabaseWithProps(&g_ceGuidInitDB, &ced, wProps, propSpec);
  if( 0==oid )
  {
  DWORD error = GetLastError();
  }
  3.4. 数据库操作
  3.4.1. 读取记录
  根据对系统联系人 EDB 数据库记录的分析,可以得到各个属性的属性PropID,下面列举一部分属性ID。读者可以根据读取到的联系人属性记录值,推导出每个联系人属性相应的PropID。
  const DWORD ContactNamePropid = 0x0080001f; // 名 const DWORD ContactSurNamePropid = 0x0084001f; // 姓 const DWORD ContactPhonePropid= 0x0096001f; // 移动电话
  const DWORD ContactHomePhonePropid = 0x0099001f; // 家庭电话
  const DWORD ContactHomePhone2Propid = 0x009a001f; // 家庭电话2
  const DWORD ContactWorkPhonePropid = 0x0097001f; // 工作电话
  const DWORD ContactWorkPhone2Propid = 0x0098001f; // 工作电话2
  通过前文打开的联系人数据库句柄g_hContactsDB,并且也已经知道了各个属性的
  PropID,就可以开始对联系人进行读取了。下面的代码片断,实现读取全部联系人的功能。
  // 首先把数据库位置定位到第一条记录。
  CEOID oid = CeSeekDatabaseEx(g_hContactsDB,CEDB_SEEK_BEGINNING ,0,0,NULL);
  while(oid) // 如果联系人记录存在
  {
  PCEPROPVAL pRecord = NULL; // 存储记录属性的数据结构指针
  PBYTE pStringStore = NULL; // 系统分配的属性存储的内存空间地址
  DWORD dwRecSize; // 内存空间的大小
  WORD wProps; // 读取到的联系人属性的数量
  oid = CeReadRecordPropsEx (g_hContactsDB, CEDB_ALLOWREALLOC,&wProps,
  NULL,&(LPBYTE)pStringStore, &dwRecSize, NULL);
  if(0!=oid) // 读取成功
  {
  pRecord = (PCEPROPVAL)pStringStore;
  for(int i = 0; i guid; // 获得数据库卷的CEGUID
  CEOID dbOid = pCalllogNotification-> oidParent; // 获得记录所在的数据库OID
  CEOID oid = pCalllogNotification->oid; // 获得发生变化的记录OID
  switch ( pCalllogNotification->uType )
  {
  case DB_NOTIFY_RECORD_CREATED: // 新建了一个联系人记录
  {
  // 在这里,通过获得的记录oid,可以读取新建联系人的姓名、号码等属性
  // 处理完之后,需要释放消息
  CeFreeNotification(&edbContactsRequest, pCalllogNotification);
  break;
  }
  case DB_NOTIFY_RECORD_CHANGED: // 修改了一条记录
  case DB_NOTIFY_RECORD_DELETED: // 删除了一条记录
  default:
  // 处理完之后,需要释放消息
  CeFreeNotification(&edbContactsRequest, pCalllogNotification);
  Break;
  }
  return S_OK;
  }
  4. 结束语
  通过上面的实例介绍, 读者可以初步掌握数据库的常用操作技术, 能够根据需要对数据库进行开发应用。数据库开发是比较复杂的问题,要开发使用功能强大、性能稳定的数据库, 需要掌握的知识很多。特别是对数据库进行操作时由于函数参数较多往往嵌套多个结构体, 而且比较复杂, 涉及到很多的结构体和指针变量, 在写代码时要特别注意指针和内存的问题, 要防止内存泄露,指针要及时进行清空。希望本文能对WM 平台的EDB 数据库开发起到抛砖引玉的作用。
  参考文献
  [1] 傅曦,齐宇,徐骏.Windows Mobile 手机应用开发[M]. 北京:人民邮电出版社,2005
  [2] 刘彦博,胡砚,马骐.Windows Mobile平台应用与开发[M]. 北京:人民邮电出版社,2006
  [3] Microsoft.MSDN Mobile 专区[OL]. http://msdn.microsoft.com/en-us/windowsmobile/defa ult.aspx,2006
  [4] 田东风.Windows CE 应用程序设计[M].北京:机械工业出版社,2005
  [5] 沈建国,田增山.Windows CE 5.0 EDB数据库的应用与开发[D].北京:电脑编程技巧与维护,2007.10
  Windows Mobile Platform EDB Database
  Application Develop
  Cheng Lehu1, Zou Shihong1, Linyu2, Shi Wenyong2
  1. State Key Lab of Networking and Switching Technology,
  Beijing University of Posts and Telecommunications, Beijing (100876)
  2. Beijing NetQin Tech. Co., Ltd., Beijing (100013)
  Abstract
  This paper first introduced the basic knowledge of Windows Mobile platform's EDB database, and
  common data structure and EDB API. Then, based on Windows Mobile's own Contacts EDB database instance, explain how to develop EDB application, such as create EDB database, reading records, add records, delete records and seek records. This paper also introduced EDB transaction and EDB database notification mechanism in detail. Keywords: Mobile Application, Windows Mobile, EDB, Contacts 作者简介:程乐乎,男,1984年生,硕士研究生,主要研究方向是Windows Mobile 操作系统及其应用编程。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics