Windows Mobile下Native C++访问SqlCe的封装

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介:

背景

进行Windows Mobile的应用的开发,很多时候需要对数据库进行访问,存储和读取。可是微软没有为Native C++提供象ADO.NET下的封装,所以我自己封装了一个SqlCe访问类。

简述

本文讲述在Windows Mobile和Wince下,Native C++访问SqlCe的封装类的实现。由于微软没有为C++提供像ADO.NET的封装,为Native C++访问SqlCe制造了一定的难度,因此对OleDB访问SqlCe进行封装,方便使用SQL语句对SqlCe进行操作。

SqlCe访问技术概述

ADO.NET

.NET Compact Framework逐渐成为Windows Mobile和Wince的开发的主流,微软为CF.NET提供了ADO.NET访问SqlCe,对SqlCe的访问封装在System.Data.SqlServerCe下,和其他数据库(SQL Server, Oracle)访问基本兼容,但是不支持DbProviderFactory。例如下面的代码不能通过编译,因为没有SqlCeProviderFactory类。

DbProviderFactory factory = SqlCeProviderFactory.Instance;

我之前封装了一个ADO.NET的SqlCe访问类,可以参考 .NET Compact Framework下SQL CE的使用 和 实现了SqlCeHepler的单元测试类见.NET Compact Framework下的单元测试

OleDb

在Native的世界,可以通过OleDb来访问SqlCe。OleDb封装在sqlceoledb35.dll下,使用OleDb需要安装一个Cab包如下:

C:\Program Files\Microsoft SQL Server Compact Edition\v3.5\Devices\wce500\armv4i\sqlce.repl.ppc.wce5.armv4i.CAB

上述路径根据平台有所不同。

注意上述sqlceoledb35.dll只是支持SqlCe 3.5,微软对不同版本的SqlCe的兼容性不是很好,可以参考 SQL Server Express和SQL Server Compact的应用 和 .NET Campact Framework下SQL CE兼容性问题 了解SqlCe的历史我兼容性问题。

本文后续会重点讲述OleDb。

ADO

在Windows Mobile和Wince平台,微软官方不支持ADO。但是有一个社区实现,可以参考 A set of ADOCE classes。我没有试过,所以不好评论。

 

实现

下面讲述如何基于OleDb实现对SqlCe的访问。

文档和Samples

微软提供了在线文档,可以在 Microsoft SQL Server Compact 3.5 Books Online and Samples下载。上述链接只是包含在线文档,没有提供例子程序的,所以这个名字有点骗人感情之嫌。虽然提供了在线文档,但是文档的质量不高,有些细节没讲,例如调用ICommand::Execute的入口参数就没有讲,我做的时候只能自己试。

虽然上面的链接不提供Samples,但是我们还有另外一个方法取得Samples。在

C:\Program Files\Microsoft SQL Server 2005 Mobile Edition\Samples\NorthwindOleDb

下可以得到Sample代码,前提是安装了Microsoft SQL Server 2005 Mobile Edition。但是要注意不同SqlCe版本实现有所不同,这个代码要结合上面的Online book修改才行。

基于SQL语句的实现

微软的例子程序NorthwindOleDb提供了通过OleDb访问SqlCe的方法,但是不提供对SQL语句的封装,直接对表的访问效率比较高,但是也有很大的不便性。因为每个操作都单独封装一个函数,每个函数大概至少需要100行代码,而且有指针等资源的分配,释放等操作,一旦没有处理好就发生内存泄漏了。所以我偏向于使用统一的SQL语句接口对SqlCe进行操作,虽然牺牲了点性能,却提供了方便性。下面是当前版本的封装类。这个类是基于João Paulo Figueira 的OleDbClientLib3实现的。

SqlCeHelper3

打开关闭

bool Open(const CString& dbPath);
void Close();

上面为打开和关闭SqlCe数据库链接的操作,这里实现为长链接,也就是不调用Close()的话,数据库的Session一直链接着,这样的好处是缩短访问时间。

新建删除

bool CreateDatabase(const CString& dbPath);
bool DeleteDatabase(const CString& dbPath);

由于SqlCe是in-process数据库,物理上表现为就一个文件,可以方便新建和删除,上述接口就是新建和删除SqlCe数据库,新建后自动打开数据库的Senssion了。

增删改操作

int  ExecuteNonQuery(const CString& sql);

把增删改的语句调用ExecuteNonQuery()执行就可以了。

SqlCeHelper db;
HRESULT hr = db.Open(DB_FILE_NAME);
if(hr < 0)
{
CString cstr = db.GetErrorsMessage();
char* str = new char[cstr.GetLength()+1];
sprintf(str, "%S", cstr);
FAIL(str);
delete str;
}

CString sqlStr;
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);
hr = db.ExecuteNonQuery(sqlStr);
if(hr < 0)
{
CString cstr = db.GetErrorsMessage();
char* str = new char[cstr.GetLength()+1];
sprintf(str, "%S", cstr);
FAIL(str);
delete str;
}
}

db.Close();

上面是一个Insert语句的例子。

 

事务处理

void BeginTransaction();
void CommitTransaction();
void RollbackTransaction();

但是当前版本还没有事务支持。

查询操作

其实这么多操作之中查询操作的实现是最复杂的。

int     ExecuteReader(const CString& sql);

执行ExecuteReader()会根据select语句初始化一个结果集,和ADO.net的实现不一样,这个结果集不是直接通过DataSet或者DataReader来返回的,而是保持在内部的IRowset的结构里面。为了方便使用,SqlCeHelper实现了一个只读,向前的数据读取方法。

bool IsEndOfRecordSet();
void MoveNext();
void CloseReader();

int GetRowInt(const long ordinal);
double GetRowDouble(const long ordinal);
CString GetRowStr(const long ordinal);

当调用ExecuteReader()后,可以调用IsEndOfRecordSet()判断结果集是否为空。MoveNext()为移动到下一条记录。GetRowInt(), GetRowDouble()和 GetRowStr()为读取当前记录的数据。CloseReader()关闭结果集。

    SqlCeHelper db;
HRESULT hr = db.Open(DB_FILE_NAME);
if(hr < 0)
{
CString cstr = db.GetErrorsMessage();
char* str = new char[cstr.GetLength()+1];
sprintf(str, "%S", cstr);
FAIL(str);
delete str;
}

CString sqlStr;
sqlStr.Format(L"SELECT * FROM T1");
hr = db.ExecuteReader(sqlStr);
if(hr < 0)
{
CString cstr = db.GetErrorsMessage();
char* str = new char[cstr.GetLength()+1];
sprintf(str, "%S", cstr);
FAIL(str);
delete str;
}

while(!db.IsEndOfRecordSet())
{
wprintf(L"F1=[%d], F2=[%s], F3=[%s]\n", db.GetRowInt(1), db.GetRowStr(2), db.GetRowStr(3));
db.MoveNext();
}
db.CloseReader();
db.Close();

上面演示整个读取过程。

Unit Test

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

TO-DO-LIST

**Support to open the database with password 
**Support to specify the Open Mode 
**Support to load Ole Db without COM registry. 
**Support Transactions 
**Support Parameters

关于项目

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

SqlCeHelper - Native C++ SQL Helper class for SQL Server Compact

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

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


    本文转自Jake Lin博客园博客,原文链接:http://www.cnblogs.com/procoder/archive/2009/09/09/Windows-Mobile-SQLCE-Native.html,如需转载请自行联系原作者



相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS&nbsp;SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/sqlserver
相关文章
|
1月前
|
存储 负载均衡 Java
如何配置Windows主机MPIO多路径访问存储系统
Windows主机多路径(MPIO)是一种技术,用于在客户端计算机上配置多个路径到存储设备,以提高数据访问的可靠性和性能。本文以Windows2012 R2版本为例介绍如何在客户端主机和存储系统配置多路径访问。
83 13
如何配置Windows主机MPIO多路径访问存储系统
|
28天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
66 4
|
2月前
|
应用服务中间件 Shell PHP
windows系统配置nginx环境运行pbootcms访问首页直接404的问题
windows系统配置nginx环境运行pbootcms访问首页直接404的问题
|
2月前
|
Apache 数据中心 Windows
将网站迁移到阿里云Windows系统云服务器,访问该站点提示连接被拒绝,如何处理?
将网站迁移到阿里云Windows系统云服务器,访问该站点提示连接被拒绝,如何处理?
|
2月前
|
域名解析 缓存 网络协议
Windows系统云服务器自定义域名解析导致网站无法访问怎么解决?
Windows系统云服务器自定义域名解析导致网站无法访问怎么解决?
|
2月前
|
弹性计算 关系型数据库 网络安全
阿里云国际版无法连接和访问Windows服务器中的FTP服务
阿里云国际版无法连接和访问Windows服务器中的FTP服务
|
3月前
|
数据安全/隐私保护 C语言 C++
C++(七)封装
本文档详细介绍了C++封装的概念及其应用。封装通过权限控制对外提供接口并隐藏内部数据,增强代码的安全性和可维护性。文档首先解释了`class`中的权限修饰符(`public`、`private`、`protected`)的作用,并通过示例展示了如何使用封装实现栈结构。接着介绍了构造器和析构器的使用方法,包括初始化列表的引入以及它们在内存管理和对象生命周期中的重要性。最后,通过分文件编程的方式展示了如何将类定义和实现分离,提高代码的模块化和复用性。
|
3月前
|
JavaScript 前端开发 Java
通过Gtest访问C++静态、私有、保护变量和方法
通过Gtest访问C++静态、私有、保护变量和方法
87 0
|
4月前
|
开发框架 JavaScript .NET
【Azure 应用服务】Azure Mobile App (NodeJS) 的服务端部署在App Service for Windows中出现404 Not Found
【Azure 应用服务】Azure Mobile App (NodeJS) 的服务端部署在App Service for Windows中出现404 Not Found
|
4月前
|
Python Windows
【Azure 应用服务】App Service For Windows 环境中部署Python站点后,如何继续访问静态资源文件呢(Serving Static Files)?
【Azure 应用服务】App Service For Windows 环境中部署Python站点后,如何继续访问静态资源文件呢(Serving Static Files)?