/// 将源数据库表的数据复制到 SQL Server Compact Edition 数据库的表中。
/// </summary>
/// <param name="srcConnection">源数据库连接接对象。</param>
/// <param name="destConnection">目标 SQL Server Compact Edition 数据库连接对象。</param>
/// <param name="queryString">源数据的查询语句。</param>
/// <param name="destTableName">目标数据库表名称。</param>
/// <remarks>本方法假设目标 SQL Server Compact Edition 数据库的表已经存在。</remarks>
public static void CopyTable(
IDbConnection srcConnection,
SqlCeConnection destConnection,
string queryString,
string destTableName)
{
IDbCommand srcCommand = srcConnection.CreateCommand();
srcCommand.CommandText = queryString;
SqlCeCommand destCommand = destConnection.CreateCommand();
destCommand.CommandType = CommandType.TableDirect; //基于表的访问,性能更好
destCommand.CommandText = destTableName;
try
{
IDataReader srcReader = srcCommand.ExecuteReader();
SqlCeResultSet resultSet = destCommand.ExecuteResultSet(
ResultSetOptions.Sensitive | //检测对数据源所做的更改
ResultSetOptions.Scrollable | //可以向前或向后滚动
ResultSetOptions.Updatable); //允许更新数据
object [] values;
SqlCeUpdatableRecord record;
while (srcReader.Read())
{
// 从源数据库表读取记录
values = new object [srcReader.FieldCount];
srcReader.GetValues(values);
// 把记录写入到目标数据库表
record = resultSet.CreateRecord();
record.SetValues(values);
resultSet.Insert(record);
}
srcReader.Close();
resultSet.Close();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
}
}
由于 CopyTable 函数的源数据库连接参数采用的是 IDbConnection 接口,所以该方法可以支持多种源数据库。代码中还利用 IDataReader.GetValues(object[] values) 和 SqlCeUpdatableRecord.SetValues(object[] values) 更方便的读取和写入数据。
在使用 CopyTable 函数之前必须预先创建好 SQL CE 数据库的表结构,并且 SQL CE 数据库的表结构必须跟 queryString 参数(select SQL 语句)的查询结果的表结构对应。
通过下面的代码使用 CopyTable 函数:
string srcConnString = "Data Source=(local);Initial Catalog=Northwind;Integrated Security=True" ;
SqlConnection srcConnection = new SqlConnection(srcConnString);
// 创建目标 SQL Server Compact Edition 数据库连接对象
string destConnString = @"Data Source=C:/Northwind.sdf" ;
SqlCeConnection destConnection = new SqlCeConnection(destConnString);
VerifyDatabaseExists(destConnString); //创建数据库结构
srcConnection.Open();
destConnection.Open();
// 复制数据
CopyTable(srcConnection, destConnection, "SELECT * FROM Products", "Products" );
CopyTable(srcConnection, destConnection, "SELECT * FROM Employees", "Employees" );
srcConnection.Close();
destConnection.Close();
五、创建数据库结构
上面说到在使用 CopyTable 函数之前 SQL CE 数据库必须存在并且表结构都创建好。我们现在就来编写创建数据库结构的代码。首先创建一个名为 DbSchema.sql 的文件,并编写 Northwind 数据库中的 Products 和 Employees 表的创建脚本:
ProductID int NOT NULL CONSTRAINT PK_Products PRIMARY KEY ,
ProductName nvarchar(40) NOT NULL ,
SupplierID int NULL ,
CategoryID int NULL ,
QuantityPerUnit nvarchar(20) NULL ,
UnitPrice money NULL ,
UnitsInStock smallint NULL ,
UnitsOnOrder smallint NULL ,
ReorderLevel smallint NULL ,
Discontinued bit NOT NULL
)
GO
CREATE TABLE Employees(
EmployeeID int NOT NULL CONSTRAINT PK_Employees PRIMARY KEY ,
LastName nvarchar(20) NOT NULL ,
FirstName nvarchar(10) NOT NULL ,
Title nvarchar(30) NULL ,
TitleOfCourtesy nvarchar(25) NULL ,
BirthDate datetime NULL ,
HireDate datetime NULL ,
Address nvarchar(60) NULL ,
City nvarchar(15) NULL ,
Region nvarchar(15) NULL ,
PostalCode nvarchar(10) NULL ,
Country nvarchar(15) NULL ,
HomePhone nvarchar(24) NULL ,
Extension nvarchar(4) NULL ,
Photo image NULL ,
Notes ntext NULL ,
ReportsTo int NULL ,
PhotoPath nvarchar(255) NULL
)
GO
这段 SQL 语句不能直接在 SQL CE 上执行的,我们需要进行一些字符串的处理。现在将该文件添加到 Visual Studio 2005 的项目资源中。
并添加执行这段 SQL 创建数据库表结构的方法:
{
using (SqlCeConnection connection = new SqlCeConnection(connectionString))
{
if (! File.Exists(connection.Database))
{
using (SqlCeEngine engine = new SqlCeEngine(connection.ConnectionString))
{
engine.CreateDatabase();
string[] commands = Properties.Resources.DbSchema.Split(
new string[] { "GO" }, StringSplitOptions.RemoveEmptyEntries);
SqlCeCommand command = new SqlCeCommand();
command.Connection = connection;
connection.Open();
for (int i = 0; i < commands.Length; i++ )
{
command.CommandText = commands[i];
command.ExecuteNonQuery();
}
}
}
}
}
六、总结
性能测试的结果会因为环境的不同而有一些出入,我想留给大家去做会更有意义。不过我相信这是当前性能比较好的向 SQL CE 导入数据的方法之一。目前需要预先创建好 SQL CE 的表结构是美中不足的地方,我会在后续文章中实现一个自动根据查询结果生成创建 SQL CE 表结构的 SQL 语句的代码,其实并不难。