背景

当前移动设备开发领域,在本地数据存储方面,Sqlite几乎成了事实标准,Andriod (android.database.sqlite),iPhone (SQLite for iPhone SDK 和 FMDB for iPhone),Palm WebOS (webOS SQL Tutorial),新版本的Symbian也直接built-in Sqlite了(20 million Symbian smartphones shipped in Q3 2007 Newer versions of the SymbianOS have SQLite built in.)。那么作为移动设备领域的重要一员Windows Mobile怎么可能错过Sqlite呢。

简介

Sqlite几乎成立移动设备开发领域数据存储方面的事实标准。Sqlite已经广泛被使用到Andriod,iPhone,WebOS以及Symbian等平台了,本文讲述在Windows Mobile平台下如何使用Native C++访问Sqlite,同时讲述一个封装类的实现和使用。

Sqlite源码

Sqlite源码可以到 SQLite Download Page 下载,我为了省事直接使用了sqlite.phxsoftware.com的在Windows Mobile下的build工程。

Sqlite的C++封装

封装我使用了Tyushkov Nikolay的封装CppSQLite3U。这里感谢egmkang的推荐。CppSQLite3U封装是对Sqlite原有纯C的api进行OO的C++的封装。主要封装以下几个类:

1. CppSQLite3DB 数据库类,用于新建数据库,打开关闭链接,执行DDL和DML。

2. CppSQLite3Statement 用于执行参数化的SQL。CppSQLite3DB 可以执行SQL但是不支持参数化。

3. CppSQLite3Query 用于读出执行Select后的查询结果。

4. CppSQLite3Exception 用于捕捉异常。

简单明了的封装了Sqlite。

封装类的使用

使用方法源自于我对CppSQLite3U类的单元测试。见源文件的SqliteHelperTest.h。

创建数据库文件

TEST(SqliteHelper, CreateDatabase){try{        CppSQLite3DB db;        DeleteFile(DB_FILE_NAME);        db.open(DB_FILE_NAME);        db.close();    }catch(CppSQLite3Exception e)    {        FAIL(ToString(e.errorMessage()).c_str());    }    TRACE("Create database successful.");}

调用CppSQLite3DB 的open()函数的时候如果发现没有数据库文件就会新建一个数据库文件。Sqlite的源代码如下(见sqlite3.c):

rc = openDatabase(zFilename8, ppDb,                  SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);

执行DDL

TEST(SqliteHelper, CreateTable){try{        CppSQLite3DB db;        db.open(DB_FILE_NAME);        db.execDML(L"create table T1(F1 int, F2 char(20), F3 char(20));");

        db.close();    }catch(CppSQLite3Exception e)    {        FAIL(ToString(e.errorMessage()).c_str());    }    TRACE("Create table successful.");}

执行CppSQLite3DB 的execDML()函数可以执行DDL。Sqlite3的数据类型定义和其他常见关系型数据库有很大区别,Sqlite3数据类型定义信息是和具体的数据绑定的而不是和字段定义绑定,也就是动态的,同一个字段的不同记录可以存储不同的数据类型的数据。所以在定义表的时候定义字段类型不是必须的,具体可以参考 Datatypes In SQLite Version 3。

执行DML

TEST(SqliteHelper, InsertTable){try{        CppSQLite3DB db;        db.open(DB_FILE_NAME);

        CString sqlStr;        time_t tmStart, tmEnd;        tmStart = time(0);for(int i=0; i<max; ++i)        {            SYSTEMTIME currentTime;                GetLocalTime(&currentTime);            sqlStr.Format(L"INSERT INTO T1 (F1, F2, F3) VALUES(%d, 'STR%d', '%d-%d-%d %d:%d:%d')",                 i, i, currentTime.wYear, currentTime.wMonth, currentTime.wDay, currentTime.wHour, currentTime.wMinute, currentTime.wSecond);            db.execDML(sqlStr);        }        tmEnd = time(0);char ch[255];        sprintf(ch, "Insert table successful in %d seconds", tmEnd-tmStart);        TRACE(ch);        db.close();    }catch(CppSQLite3Exception e)    {        FAIL(ToString(e.errorMessage()).c_str());    }}

CppSQLite3DB 的execDML()函数不仅可以执行DDL,而且可以执行DML。同理Update和Delete语句一样。

执行Scalar

TEST(SqliteHelper, SelectScalarBeforeInsert){try{        CppSQLite3DB db;        db.open(DB_FILE_NAME);

int count = db.execScalar(L"SELECT COUNT(*) FROM T1;");char ch[255];        sprintf(ch, "%d rows in T1 table", count);        TRACE(ch);        db.close();    }catch(CppSQLite3Exception e)    {        FAIL(ToString(e.errorMessage()).c_str());    }    TRACE("Select scalar before insert successful.");}

CppSQLite3DB 的execScalar()函数模仿ADO.NET的SqlCommand.ExecuteScalar 用于取第一条记录的一个字段的值,一般用于聚集函数的查询。

执行查询

TEST(SqliteHelper, SelectAfterInsert){try{        CppSQLite3DB db;        db.open(DB_FILE_NAME);        CppSQLite3Query q = db.execQuery(L"SELECT * FROM T1;");

        std::string str;char ch[255];while (!q.eof())        {            sprintf(ch, "F1=%d, F2=%S, F3=%S\n", q.getIntField(0), q.getStringField(1), q.getStringField(2));            str += ch;            q.nextRow();        }        TRACE(str.c_str());        db.close();    }catch(CppSQLite3Exception e)    {        FAIL(ToString(e.errorMessage()).c_str());    }}

查询需要借助CppSQLite3Query 来取出查询的结果。eof()函数判断是否结束。nextRow()移动到下一条记录。getIntField()函数和getStringField()函数为读取当前记录的特定字段的值。

使用事务

TEST(SqliteHelper, InsertTableWithTransaction){try{        CppSQLite3DB db;        db.open(DB_FILE_NAME);

        CString sqlStr;        time_t tmStart, tmEnd;        tmStart = time(0);        db.execDML(L"begin transaction;");for(int i=0; i<max; ++i)        {            SYSTEMTIME currentTime;                GetLocalTime(&currentTime);            sqlStr.Format(L"INSERT INTO T1 (F1, F2, F3) VALUES(%d, 'STR%d', '%d-%d-%d %d:%d:%d')",                 i, i, currentTime.wYear, currentTime.wMonth, currentTime.wDay, currentTime.wHour, currentTime.wMinute, currentTime.wSecond);            db.execDML(sqlStr);        }        db.execDML(L"commit transaction;");        tmEnd = time(0);char ch[255];        sprintf(ch, "Insert table successful in %d seconds", tmEnd-tmStart);        TRACE(ch);        db.close();    }catch(CppSQLite3Exception e)    {        db.execDML(L"rollback transaction;");        FAIL(ToString(e.errorMessage()).c_str());    }}

在Sqlite上事务的使用非常简单。通过CppSQLite3DB 的execDML()函数来打开,提交和回退事务。Sqlite在事务处理上,语法层面上和MS SQL Server有点类似,默认是自动事务(AutoCommit),关于事务处理我之前写过一篇文章,有兴趣可以参考下 MS SQL Server和Oracle对数据库事务处理的差异性。也可以参考

BEGIN TRANSACTION。 从测试结果看,批量处理数据,显式使用事务和自动事务在处理时间上差别很大。

在insert 100条数据时,显式使用事务小于1秒钟完成,而使用自动事务的话需要4秒钟。为什么有这么大的差别,我没有仔细研究Sqlite的源码,我从通用数据库的概念来讲述,事务其中一个特性是持久性(Durability),也就是凡是提交了的事务的数据都需要持久化,需要持久化就需要写硬盘,在移动设备是flash,写永久存储设备的速度是远远慢于写内存的速度的,所以速度差异点在IO。

Unit Test

项目开发中使用了TDD,关于Unit Test可以参考Wince和Windows Mobile下native C++的单元测试 和 Windows Mobile下使用CppUnitLite输出测试结果 。

关于项目

我把项目host到codeplex了,项目主页链接如下:

SqliteHelper - Native C++ wrapper class for Sqlite on Windows Mobile & Wince

检查和下载最新版本链接如下

http://sqlitehelper.codeplex.com/SourceControl/ListDownloadableCommits.aspx

如果你喜欢这个项目,如果这些代码能帮助你,请回复,上次我做了一个SqlCeHelper,参考 Windows Mobile下Native C++访问SqlCe的封装。某一天我收到一个消息,一个人告诉我他google了一个星期也没一个搞定SqlCe,看了我的文章搞定了,我还是很高兴能帮到别人。

Windows Mobile下访问Sqlite的Native C++封装相关推荐

  1. 关于在Windows Mobile下今日插件使用WTL的问题

    简介 本文讲述在今日插件开发中整合WTL遇到的问题,问题已经解决,看解决部分. 问题 最近一段时间都在开发今日插件(Today Plug-in).开始把代码都写的差不多了,整合了Sqlite和WTL, ...

  2. Windows Mobile下使用CppUnitLite输出测试结果

    背景 TDD测试驱动开发是当前流行的开发方法及模式.遵循TDD的方法对开发程序库(Library)特别有用,因为Library就是为第三方提供一定功能接口的实现,使用TDD的方法可以预先为定义的接口提 ...

  3. 实测Windows Mobile下卡巴斯基手机安全软件表现

    实测Windows Mobile下卡巴斯基手机安全软件表现 文/ 图 鲜橙加冰(王文文) [51CTO.com 独家特稿]随着科技的不断发展和3G技术的不断成熟,我国正迅速进入一个全新的3G时代.大量 ...

  4. Windows Mobile下猜数字游戏的TDD实现

    背景 早上看了TDD by example (1) -- 挑战,觉得有趣,实现一个Windows Mobile版本.很多年前我也有一台文曲星,也常常玩这个猜数字游戏,所以尝试在Windows Mobi ...

  5. Windows Mobile下GPS管理软件NavsGo之GPS侦测功能的开发

    简述 在上篇文章 Windows Mobile下GPS管理软件NavsGo之GPS监控功能的开发 概述了NavsGo项目以及讲述了GPS监控功能的开发,GPS.net控件的使用,这篇文章讲述侦测功能的 ...

  6. Windows Mobile下使用Native C++开发日志类

    背景 这段业余时间一直都在开发iToday.在iToday中加入日志管理.关于iToday,可以参考那些一些文章. 开源(Open Source)那些事儿 (一) 开源那些事儿 (二) - iToda ...

  7. Windows Embedded CE和Windows Mobile下ActiveSync开发

    背景 用过Windows Mobile的人大概都有使用USB线链接手机到PC的经历,这一般由ActiveSync来完成软件功能.ActiveSync在Windows Embedded CE以及Wind ...

  8. Windows mobile 下读取手机SIM卡信息

    最近在忙一个移动警务的项目,需要获取SIM卡的信息,来做身份的验证.考虑到获取:国际移动设备识别码(IMEI:International Mobile Equipment Identification ...

  9. Windows/Linux下C++对于UUID的跨平台封装

    Universally Unique Identifier,UUID,通用唯一识别码.是用于计算机体系中以识别信息数目的一个128位标识符,这个东西很有用,在分布式系统中经常用于标识一个结点.根据标准 ...

最新文章

  1. C# 将DataTable数据源转换成实体类
  2. 建筑与建筑群综合布线系统工程验收规范_GB50XXX电气施工规范
  3. 结构张量用于区分平坦、边缘、角点区域
  4. android调试神器Stetho
  5. 补码(为什么按位取反再加一):告诉你一个其实很简单的问题
  6. 使用SAP OData offline库实现Android应用的离线(offline)模式
  7. 图像分类任务中的tricks总结
  8. Ubuntu-安装MySQL5.7并配置用户名密码
  9. fclose会写入硬盘吗 linux_Linux 文件操作总结
  10. C#基础List与ArrayList
  11. natapp外网穿透使用教程Windows
  12. 用大白话谈谈XSS与CSRF
  13. Require statement not part of import statement. eslint@typescript-eslint/no-var-requires报错修改
  14. 微信开发者工具 wxmi修改模版颜色_Logo设计模版与设计管理
  15. 关于LED金线的相关知识
  16. 张大哥笔记-个人站长要具备那些心态来运营自己的网站
  17. 【姿态估计】PCK(Percentage of Correct Keypoints)指标及代码实现
  18. Java项目:律师事务所律师管理系统(java+SSM+HTML+JS+jsp+mysql)
  19. 2015百度校园招聘面试题
  20. 从零开始以太坊(一)

热门文章

  1. Python学习笔记011——内置函数exec()
  2. 数据中心行业人士如何进行继续教育
  3. [BZOJ 2002][Hnoi2010]Bounce 弹飞绵羊(分块)
  4. Codeforces Round #370 (Div. 2) A. Memory and Crow 水题
  5. 和lock一起学beego 博客系统开发为例(六)
  6. 经典题---数组改“貌”
  7. 改写了一个shell写的cdn节点测试代码
  8. 黑莓作为猫带笔记本上网
  9. 检索数据表中重复的记录
  10. 全国计算机等级考试三级网络技术考试大纲