2.4 查询计划信息 有一些APIs被用来执行查询数据库结构(索引,表和结构)。数据库基类,RdbDatabase提供了下列方法: ·TableNamesL():封装在CDbTableName中的表名列表方法。 ·IndexNamesL():封装在CDbIndexNames中的索引名列表方法。该方法采用表名参数。 ·ColSetL():封装在CDbColSet中的表列定义方法。该方法采用一个一个表名参数。 ·KeyL():表索引定义方法,该方法使用一个表名和一个索引名做为参数。 表的列定义CDbColSet也可对表或一个SQL视图进行查询(参见3.1节,“行集定义”)使用他们的基类方法RdbRowSet::ColSetL()。使用这个方法或利用TdbColSetIter 类便可以重新申明CdbColSet。
下列样例代码从Books表获得列名与规格。结果打包进入CdesCArryFlat。 ... private: // 成员数据 RDbStoreDatabase iBookDb; ... // 数组中的项格式化为 <列名>: <列规格> CDesCArrayFlat* CBookDb::ColumnNamesAndSizesL() { RDbTable booksTable; TBuf<KDbMaxColName> columnNameAndSize; _LIT(KDelimiter, ": "); _LIT(KNoSize,"No size"); // 打开Books表 User::LeaveIfError( booksTable.Open(iBookDb, KBooksTable, booksTable.EReadOnly)); CleanupClosePushL(booksTable); // 记忆弹出与关闭 CDesCArrayFlat* resultArray = new (ELeave)CDesC16ArrayFlat(KArrayGranularity); CleanupStack::PushL(resultArray); //重新声明Books 表的列,析取列名与列规格(仅对文本列的规格) CDbColSet* colSet = booksTable.ColSetL(); CleanupStack::PushL(colSet); TDbColSetIter colIter(*colSet); while(colIter) { columnNameAndSize.Zero(); columnNameAndSize.Append(colIter->iName); columnNameAndSize.Append(KDelimiter); if(colIter->iType == EDbColText) columnNameAndSize.AppendNum(colIter->iMaxLength); else columnNameAndSize.Append(KNoSize); resultArray->AppendL(columnNameAndSize); colIter++; } CleanupStack::PopAndDestroy(colSet); CleanupStack::Pop(resultArray); //从清除栈中探出booksTable,关闭清除栈。 CleanupStack::PopAndDestroy(); return resultArray; }
2.5 打开与关闭数据库 本节中描述的数据库创建自2.2节,“创建一个数据库”,数据库已打开并在等待数据操作。在实践中,打开一个已有数据库是很频繁的事情。 如2.2节讨论的一样,数据库可以独占客户端模式打开与以客户/服务器共享模式打开。RDbNamedDatabase对这两种都支持,而RDbStoreDatabase API仅能以独占客户端模式打开数据库。 推荐使用RDbNamedDatabase API。客户端访问模式效率略高,但是由于文件被锁定,数据库无法访问其它应用程序。对于通常的的应用程序,推荐使用客户/服务器模式。
客户/服务器 模式 下列代码片段显示了以客户/服务器模式打开和关闭一个数据库。执行过程需要使用RDbNamedDatabase和数据库服务器会话RDbs。 ... private: //数据成员 RDbs iDbSession; RDbNamedDatabase iBookDb; ... void CBookDb::OpenDbInClientServerModeL(const TFileName& aExistingBookFile) { User::LeaveIfError(iDbSession.Connect()); User::LeaveIfError(iBookDb.Open(iDbSession, aExistingBookFile)); } ... // 打开数据库 void CBookDb::CloseDb() { iBookDb.Close(); //注意关闭的顺序. iDbSession.Close(); } RdbNamedDatabase的Open方法打开数据库。其采用一个开启(连接)数据库会话RDbs。 数据库与会话都用Close()方法关闭。 为了保证清理CbookDb销毁过程,析构器应调用CloseDb;通常用户使用CloseDb。但是,当打开数据库(iBookDb.Open)时,使用OpenDbInClientServerModeL可能会出现RDbs会话未关闭的情况。
客户端模式 下列代码段展示了打开与关闭一个使用RDbNameDatabase API客户端模式的数据库。除了使用文件服务器会话RFs 替代数据库服务器会话RDbs,这些代码与客户/服务器的代码相类似。 ... private: // 数据成员 RFs iFsSession; RDbNamedDatabase iBookDb; ... void CBookDb::OpenDbInClientSideModeL(const TFileName& aExistingBookFile) { User::LeaveIfError(iFsSession.Connect()); User::LeaveIfError(iBookDb.Open(iFsSession, aExistingBookFile)); } ... // 打开数据库 void CBookDb::CloseDb() { iBookDb.Close(); //注意关闭的次序 iFsSession.Close(); } 如果使用RDbStoreDatabase,必须使用正确的流与会话。 ... private: //数据成员 RFs iFsSession; RDbStoreDatabase iBooksDb; CFileStore* iFileStore; ... TInt CBookDb::OpenDb(const TFileName& aExistingBookFile) { Close(); if(!BaflUtils::FileExists(iFsSession, aExistingBookFile)) { return KErrNotFound; } TRAPD(error, iFileStore = CPermanentFileStore::OpenL(iFsSession, aExistingBookFile, EFileRead|EFileWrite); // 设定文件存储类型 iFileStore->SetTypeL(iFileStore->Layout()); iBookDb.OpenL(iFileStore,iFileStore->Root()) ); if(error!=KErrNone) { return error; } iOpen = ETrue; return KErrNone; } void CBookDb::Close() { iBookDb.Close(); if(iFileStore) { delete iFileStore; //也关闭文件 iFileStore = NULL; } iFsSession.Close(); }
此文为开发视界翻译转载者请注明出处否则追究法律责任
|