在移动设备上有几种数据库可用,但是本书所用的都是SQL Server 2000 Windows CE Edition,是微软公司桌面数据库的精简版(本书以后简称为SQL Server CE)。这是为.NET Compact Framework选择的移动数据库,因为它完全支持.NET Compact Framework运行时环境和.NET Compact Framework开发环境。
大多数SQL Server CE程序有两个主要的数据库任务。
n 当断开时操作数据;
n 当设备连到桌面计算机时传送数据到SQL Server。
第一个数据库任务包含使用一般的ADO.NET类,这在前面已经讨论过了,至于提供者类,以后将讨论。在桌面系统上对于使用ADO.NET的程序员来说,.NET Compact Framework实现的ADO.NET的一般类都是很熟悉的。
第二个主要的数据库任务,SQL Server和SQL Server CE间的数据传输,不仅包括多个数据库引擎,也包括Microsoft Internet Information Services(IIS)。这是两种不同的机制,对合并复制和远程数据访问(RDA)可能有所帮助。
图11-1 显示在文件管
|
每个SQL Server数据库以单个文件储存在Windows CE设备上。推荐的文件扩展名为.sdf,文件名称为数据库的名称。如打开一个名为mydb.sdf的数据库连接,就要用全称mydb.sdf,不能用不带sdf后缀的mydb。因为每个数据库是一个文件,所以在文件管理器中可见。图11-1显示的是在文件管理器选择的一个数据库文件。
因为SQL Server CE数据库是Windows CE文件系统中的文件,所以它们能使用File和Directory类访问。例如,复制一个数据库文件、删除一个数据库文件或者测试一个指定名称的数据库文件是否存在。同样可以像其他文件那样进行约束。例如,如果文件当前未用,能删除一个数据库文件。
SQL Server CE能回收数据库文件里的空间。但它不能通过数据操作语言达到,也不能作为后台处理。为了回收SQL Server CE数据库的空间,必须使用SqlCeEngine类的Compact方法。
SQL Server CE编程比SQL Server编程简单,因为SQL Server CE支持的SQL语言是SQL Server的一个子集。因为SQL Server CE数据库是一个单用户数据库,它的安全通过一个文件密码控制,所以没必要有GRANT、DENY和PEVOKE语句。
SQL Server CE也缺少SQL Server的Transact SQL扩展:没有存储过程、语句批处理或DECLARE、SET、IF或WHILE语句。甚至一些标准的SQL也被去掉了,如不支持视图。不是所有的SQL Server数据类型都被包含,但是大多数缺少的数据类型都被转换成存在的一些类型。如Windows CE本身只支持Unicode,因此Unicode是惟一的字符数据类型。
SQL Server CE提供表、索引、默认值和参考完整性的支持。它也具有使用标准SQL数据操作语言(DML)在表中增加、修改和删除行的能力。因此,程序连接到数据库文件,提交INSERT、UPDATE和DELETE语句到数据库,能操作SQL Server CE的数据。读者可以自己写这些DML语句,或者用ADO.NET写它们,这是数据集同步到数据库的一个步骤。同样,SQL语句使用单引号描述字符串,当在代码引用SQL时,这是很方便的,因为避免了双引号的麻烦。
SQL Server CE程序可能比典型的SQL Server程序更基本,但是它应该提供了足够的功能去用于移动情况。Windows CE设备的可用内存是一个不可避免的限制,抛开这个尺寸限制,SQL Server CE为任何Windows CE程序提供足够的SQL命令集。
表11-1和表11-2分别列出了SQL Server CE支持和不支持的SQL Server的功能。
表11-1 SQL Server CE不支持的SQL Server功能
功 能 |
说 明 |
DCL(Data Control Language) |
在单用户数据库中不需要 |
DDL(Data Definition Language) |
这些大多数是对ANSI功能的SQL Server Transact SQL扩展,逻辑上,能位于SQL Server上。当运行在SQL Server CE时它必须编码到程序中 |
DML(Data Manipulation Language) |
这些大多数是对ANSI功能的SQL Server Transact SQL扩展 |
INFORMATION_SCHEMA TABLES |
这个替换成了MSysObjects 和MSysConstrains 表 |
表11-2 SQL Server CE支持的SQL Server功能
功 能 |
说 明 |
DDL |
只支持Unicode字符类型 |
DML |
|
函数 |
|
事务 |
事务分级别始终是READ COMMITTED,嵌套的限制是5,惟一的锁粒度是表级别,在事务期间有效。单向提交是惟一允许的提交类型 |
SQL Server CE语法比SQL Server烦杂些。有一个更小的footprint,意味着有更少的代码去“推断”想要的东西。如下面的SQL,在最后列定义和约束定义间缺少一个逗号,在SQL Server 2000中执行没有问题,但是在SQL Server CE中执行会产生一个语法错误。
CREATE TABLE Products
( ProductID integer not null primary key
, ProductName nchar(20) not null
, CategoryID integer not null
CONSTRAINT FKProductCategory foreign key (CategoryID)
references Categories(CategoryID)
)
图11-2 使用别名列名的
|
SELECT P.ProductID as ID
, P.ProductName as Name
, C.CategoryName as Category
FROM Products P
JOIN Categories C on C.CategoryID = P.CategoryID
对于指定一个DataGrid类的类名它并不是首选。使用DataGridColumnStyle对象更好些,因为它与底层的SELECT语句无关。
浏览和查询一个SQL Server CE数据库的主要工具是SQL Server CE Query Analyzer。像SQL Server 2000的Query Analyzer一样,SQL Server CE Query Analyzer提供了一个创建和提交特定查询的便利途径。
SQL Server CE Query Analyzer的安装依赖于安装SQL Server CE的开发环境。当安装SQL Server CE时,SQL Server CE Query Analyzer默认地不被安装到设备上。一旦Query Analyzer安装到设备上,才能直接从开始菜单或安装目录运行可执行文件Isqlw20.exe。单击文件管理器中的一个数据库文件也能打开Query Analyzer。
Query Analyzer允许查看数据库的结构信息,如图11-3所示,以及提交对那个数据库的查询,如图11-4所示。
图11-3 SQL Server CE Query 图11-4 SQL Server CE Query
Analyzer的Objects选项卡 Analyzer的SQL选项卡
Query Analyzer窗体显示一个最小化框,不是一个关闭框。如果使用Query Analyzer去查看数据库,然后在最小化框上单击,那么Query Analyzer将消失,但是没有关闭,也不关闭正在显示的数据库。任何试图访问该数据库的其他程序只能等到关闭与Query Analyzer连接的数据库(在Objects选项卡,在有数据库名称的树节点上单击,然后在工具条上单击Stop按钮)或关闭Query Analyzer(选择Tools Exit)才能访问。
访问SQL Server CE的第一个程序位于CreateDatabase项目,程序用于创建和组装一个数据库。
使用System.Data.SqlServerCe命名空间的Engine类创建一个SQL Server CE数据库。因为每个SQL Server CE数据库都是一个单个文件,要做的就是告诉Engine对象那个文件的路径和名称。也能在Engine类的构造函数或设置对象LocalConnectionString属性中告之路径和文件名。在任一情况中,必须在执行Engine类的CreateDatabase方法前指定文件名,因为这个方法不带任何参数。
创建SQL Server CE数据库的代码如图11-5所示。
图11-5 CreateDatabase程序
private string strFile = @"My Documents\ourProduceCo.sdf";
private string strConn = "Data Source=" +
@"My Documents\ourProduceCo.sdf";
private void mitemCreateDB_Click(object sender, EventArgs e)
{
if ( File.Exists(strFile) ) { File.Delete(strFile); }
SqlCeEngine dbEngine = new SqlCeEngine();
dbEngine.LocalConnectionString = strConn;
try
{
dbEngine.CreateDatabase();
}
catch( SqlCeException exSQL )
{
MessageBox.Show("Unable to create database at " +
strFile +
". Reason: " +
exSQL.Errors[0].Message );
}
}
虽然Engine类有一个CreateDatabase方法,但是它没有DropDatabase方法。删除一个数据库必须通过提交一个DROP DATABASE语句到SQL Server CE数据库或使用删除文件的File类来完成。
现在已经创建了SQL Server CE数据库,接下来就能用表、索引和数据组装它。读者可能认为,用Engine类完成这个操作,但Engine只操作一个完整的数据库,不操作数据库内的单独组件,如表。使用标准的SQL DDL语句,例如CREATE TABLE和CREATE INDEX,以及标准的SQL DML语句INSERT、UPDATE和DELETE组装SQL Server CE数据库。
提交SQL语句到数据库需要两个类,一个打开连接,一个提交语句,分别是SqlCeConnection和SqlCeCommand类。
SqlCeConnection类打开一个数据库的连接,这需要数据库文件的名称。SqlCeCommand类使用Execute方法提交一次一个SQL语句到数据库,该方法需要使用连接对象和要提交的SQL语句。SqlCeConnection和DML语句是SqlCeCommand对象的属性。在命令的Execute方法调用之前必须设置它们,类连接必须打开。表11-3描述了SQLCeComnection类的执行方法。
表11-3 SqlCeCommand类的执行方法
方 法 |
功 能 |
ExecuteNonQuery |
执行一个SQL语句,不返回行,例如INSERT或CREATE |
ExecuteScalar |
执行一个SQL语句,只返回一个值,例如SELECT SUM(Value) FROM Orders WHERE CustomerID = "ABCD" |
ExecuteReader |
执行一个SQL语句,返回多列或多行 |
下面显示的创建两个简单表的代码:
private void mitemCreateTables_Click(object sender, EventArgs e)
{
SqlCeConnection connDB = new SqlCeConnection();
SqlCeCommand cmndDB = new SqlCeCommand();
connDB.ConnectionString = strConn;
connDB.Open();
cmndDB.Connection = connDB;
cmndDB.CommandText =
" CREATE TABLE Categories " +
" ( CategoryID integer not null " +
" CONSTRAINT PKCategories PRIMARY KEY " +
" , CategoryName nchar(20) not null " +
" )";
cmndDB.ExecuteNonQuery();
cmndDB.CommandText =
" CREATE TABLE Products " +