无论您是已经决定将应用程序和数据从以前的 Pocket PC 工具(Microsoft eMbedded Visual Basic 和 Pocket Access)迁移到目前的技术(Microsoft .NET Compact Framework 和 Microsoft SQL Server CE),还是正在考虑这一决定,您都需要研究这一迁移的一些困难的理由。
第一个理由是您的设备将提高性能。在设备处理器(即使是最新的最优秀的处理器)上,性能无疑非常重要。在 SQL Server CE 中正确地设置数据库(通过适当的密钥、索引等)以后,它的性能将完全超过 Pocket Access — 有时可以超过好多倍。
第二个理由是 SQL Server CE 中更为丰富的类型系统将使您的设备能够更有效地存储数据。您可以存储在 Pocket Access 中的所有内容都可以存储在 SQL Server CE 中(不止如此)。因为该类型系统是 SQL Server 2000 的类型系统的干净子集,所以同步也会更加容易。
第三个理由是当前的数据访问中间件 (ADO.NET) 将为您提供更多的功能,以使您除了操作数据的定义以外,还可以读取和操作数据本身。新增的且本来断开的模型(由 DataSet 表明)使您在数据的使用方式方面具有更多的自由。可以将 DataSet 发送到 XML Web 服务(当您通过 ASP.NET 创建 XML Web 服务时,DataSet 类型将受到天然支持)。您可以将 DataSet 作为 XML(包含 XML 架构信息,或者在单独的文件中)存储到文件系统中(可以将 XML 从相同的文件重新读取到 DataSet 中)。
最后一个理由是,除了数据操作以外,更加丰富的 SQL 语法还使您在读取数据时具有更多的选择(使用子查询、外部联接等)。以前,您需要在检索 Recordset 之后的代码中实现大量逻辑,而现在您可以直接在它所属的 SQL 命令中完成该工作。在以前的代码中,完成诸如通过 LTRIM 或 CASE...WHEN...THEN...ELSE...END 语句格式化 SELECT 语句中的列的工作要困难得多,并且通常会更慢。
当从以前的 Pocket PC 应用程序进行的迁移同时涉及到数据和代码的迁移时,您可以在下列三个不同的级别执行迁移:
• |
数据库 |
• |
数据库中间件 |
• |
源代码 |
在数据库级别,可以将数据和代码从 Pocket Access 迁移到 SQL Server CE。主要差异与受支持的数据类型有关。当您迁移数据访问代码时,数据库中间件中的差异主要与受支持的对象以及使用这些对象的语法有关。通常,当您迁移源代码时,差异同时与不同的语言以及受支持的类库有关。下列各部分将描述不同级别之间的差异。
从 Pocket Access 迁移到 SQL Server CE
通常,以前的 Pocket PC 应用程序中的数据源自桌面计算机的 Microsoft Access 数据库。当需要进行桌面计算机复制时,通常会借助于 Microsoft ActiveSync 中内置的同步功能在桌面计算机和设备之间复制这些数据。当数据迁移到 SQL Server CE 时,第一步是将现有的 Access 数据库迁移到 SQL Server 2000。
您可以从 Access 内部执行该迁移,方法是通过连接到 SQL Server 2000 数据库的开放式数据库连接 (ODBC) 数据源来导出表。然后,您可以通过使用远程数据访问 (RDA) 将 SQL Server 2000 中的数据复制到设备上的 SQL Server CE。有关如何完成该复制的详细信息,请参阅本文中的“同步”一节。
表 1 显示了每个数据库支持的不同数据类型的映射。
表 1. 数据类型映射 | |||
Access 数据类型 | Pocket Access 类型 | SQL Server 2000 类型 | SQL Server CE 类型 |
Text |
varchar |
nvarchar |
nvarchar |
Memo |
text |
ntext |
ntext |
LongInt |
integer |
int |
int |
Int, Byte |
smallint |
smallint |
smallint |
Double, Single |
double |
float |
float |
Replication ID |
varbinary |
uniqueidentifier |
uniqueidentifier |
Date/Time |
datetime |
datetime |
datetime |
Currency |
double |
money |
money |
AutoNumber |
integer |
int |
int |
YesNo |
boolean |
bit |
bit |
OleObject |
varbinary |
image |
image |
HyperLink |
text |
ntext |
ntext |
Lookup |
varchar |
nvarchar |
nvarchar |
SQL Server 2000 支持所有 Access 数据类型,并且因为 SQL Server CE 支持(不用转换)导出中生成的所有类型,所以迁移过程中不会丢失任何信息。
从 ADO CE 迁移到 ADO.NET
ActiveX Data Objects for Windows CE (ADO CE) 是作为 ADO 的设备版本创建的,并且第一个版本 (3.0) 只支持 Pocket Access。在创建 SQL Server CE 时,更新了 ADO CE 以支持它。尽管很多以前的 Pocket PC 应用程序使用 ADO CE(3.0) 的第一个版本来访问 Pocket Access 数据库,但本节中的信息只与最新版本 (3.1) 有关。不过,下列代码示例也应该适用于 ADO CE .0。
ADO CE 支持下列对象:Recordset、Field(和集合)、Connection 和 Error(和集合)。但是,ADO CE 不支持完整(桌面)ADO 实现中包含的 Command 对象。作为 ADO CE 的扩展,ADO XCE 包含管理数据库的功能,如操作表、字段和其他数据库对象。
.NET Compact Framework 中的 ADO.NET 是完整 .NET Framework 数据访问中间件的设备版本。您可以在“System.Data.SqlServerCe”命名空间中找到 ADO.NET for SQL Server CE,它通常被称为 SQL Server CE 的托管提供程序。该托管提供程序中最重要的对象是:SqlCeConnection(用于连接到数据库)、SqlCeDataAdapter(用于访问数据库中的数据)、SqlCeCommandBuilder(用于生成 SQL 命令以便在数据库中保存数据)、SqlCeCommand(用于向数据库发出 SQL 命令)、SqlCeDataReader(用于从数据库中快速地顺序读取数据)、SqlCeEngine(用于管理数据库)以及 SqlCeException(用于错误处理)。有关 ADO CE 和 ADO.NET 的详细信息,请参阅 Microsoft Visual Studio .NET 帮助文件。
在 ADO CE 中执行的多个重要操作可以通过 ADO.NET 来完成。首先,您需要打开数据库连接。在 ADO CE 中,您可以按如下方式打开数据库。
Dim connection AS ADOCE.Connection Set connection = CreateObject("ADOCE.Connection.3.1") connection.ConnectionString = "Data Source=\MyDatabase.cdb" connection.Open
您还可以将连接字符串作为连接的 Open 方法的参数提供。调用 Connection 对象上的 Close 方法可以关闭该连接。
如果您要使用 ADO.NET 和 Visual Basic .NET,则您可以按如下方式打开数据库连接。
Dim connection As SqlCeConnection connection = New SqlCeConnection("Data Source=\MyDatabase.sdf") connection.Open()
与 ADO CE 类似,该连接的 Close 方法可以关闭该连接。
在 C# 中,相同的代码如下所示。
SqlCeConnectionconnection connection = new SqlCeConnection(@"Data Source=\MyDatabase.sdf"); connection.Open();
因为越早考虑错误处理越好,所以您可以查看 ADO CE 中是如何处理错误的。首先,您需要按如下方式设置错误处理程序:
On Error Resume Next Err.Clear
在应用程序执行每个数据库命令之后,Connection 对象上的错误集合 (Errors) 包含已经发生的任何错误。您可以通过使用以下代码让应用程序报告任何错误。
If (Err.Number <> 0) Then For i = 1 To connection.Errors.Count MsgBox connection.Errors(i).Number & " - " & _ connection.Errors(i).Description, vbCritical, "Error" Next i Err.Clear End If
对于每个错误,都会显示一个消息框,其中带有错误号和错误说明。当您使用 Pocket Access 数据库时,ADO CE 中的错误对象还支持本机错误 (NativeError) 和错误源 (Source) 的属性。
在 Visual Basic .NET 中,您可以通过使用 Try Catch 结构处理错误。下面是用于捕获和报告 ADO.NET 错误的 Visual Basic .NET 代码。
Try ' Database code Catch ex As SqlCeException If Not ex.InnerException Is Nothing Then MessageBox.Show("Inner Exception: " + ex.InnerException.ToString()) End If Dim s As StringBuilder = New StringBuilder() Dim error As SqlCeError For Each error In ex.Errors s.Append("Error Code: " + error.HResult.ToString("X")) s.Append(vbCrLf + "Message : " + error.Message) s.Append(vbCrLf + "Minor Err.: " + error.NativeError) s.Append(vbCrLf + "Source : " + error.Source) Dim numericErrorParameter As Integer For Each numericErrorParameter In error.NumericErrorParameters If numericErrorParameter <> 0 Then s.Append(vbCrLf + "Num. Par. : " + numericErrorParameter) End If Next Dim errorParameter As String For Each errorParameter In error.ErrorParameters If errorParameter.Length > 0 Then s.Append(vbCrLf + "Err. Par. : " + errorParameter) End If Next MessageBox.Show(s.ToString()) s.Remove(0, s.Length) Next End Try
在 ADO.NET 中,发生的异常(错误)包含的信息要比 ADO CE 提供的信息多得多。该信息帮助开发人员更快地查找程序错误,并且还在处理每个异常方面提供了更多的控制。首先,应用程序在消息框中报告任何内部异常,然后,应用程序在每个错误的消息框中报告(通过详细信息)异常对象 (ex) 上的集合 (Errors) 中的所有错误。
在 C# 中,代码如下所示。 try { // Database code } catch (SqlCeExceptionex) { if(ex.InnerException != null) MessageBox.Show("Inner Exception: " + ex.InnerException.ToString()); StringBuilder s = new StringBuilder(); foreach (SqlCeError error in ex.Errors) { s.Append("Error Code: " + error.HResult.ToString("X")); s.Append("\nMessage : " + error.Message); s.Append("\nMinor Err.: " + error.NativeError); s.Append("\nSource : " + error.Source); foreach (int numericErrorParameter in error.NumericErrorParameters) if(numericErrorParameter != 0) s.Append("\nNum. Par. : " + numericErrorParameter); foreach (string errorParameter in error.ErrorParameters) if(errorParameter.Length > 0) s.Append("\nErr. Par. : " + errorParameter); MessageBox.Show(s.ToString()); s.Remove(0, s.Length); } }
既然您具有连接并且可以处理返回的错误,那么您就可以开始与数据库交互了。最重要的操作是在数据库中查询数据。在 ADO CE 中,可以用下列两种方式查询数据库:通过使用 Recordset 对象上的 Open 方法,或者通过使用 Connection 对象上的 Execute 方法。
使用 Recordset 对象的代码如下所示。
Dim rs As ADOCE.Recordset Dim sql As String sql = "SELECT* FROM Customers" Set rs = CreateObject("ADOCE.Recordset.3.1") rs.Open sql, connection, adOpenDynamic, adLockOptimistic
如果您从前使用 Connection 对象,则您可以用以下行替换最后两行。
Set rs = connection.Execute(sql)
使用数据适配器的相应 Visual Basic .NET 代码如下所示。
Dim sql As String = "SELECT* FROM Customers" Dim da As New SqlCeDataAdapter(sql, connection) Dim ds As New DataSet da.Fill(ds, "Customers")
在前面的代码中,通过将数据库 (SQL) 命令和 Connection 对象作为构造函数的参数进行传递,创建了一个新的数据适配器对象 (da)。然后,通过使用该数据适配器上的 Fill 方法为 DataSet (ds) 填充了数据。Fill 方法的第二个参数设置了 DataSet 中刚刚检索的表的名称。在后台,数据适配器使用 SqlCeCommand 对象(在它的 SelectCommand 属性中)查询数据库。
在 C# 中,代码如下所示。
string sql = "SELECT* FROM Customers"; SqlCeDataAdapterda = new SqlCeDataAdapter(sql, connection); DataSetds = new DataSet; da.Fill(ds, "Customers");
ADO.NET 中提供的另一种读取数据的方式是 SqlCeDataReader。您可以使用它以一种非常高效的方式来顺序读取数据。当性能很重要以及数据量很高时,您应该考虑该选项。以下代码显示了一个有关如何使用 SqlCeDataReader 的示例。
Dim sql As String = "SELECT* FROM Customers" Dim cmd As New SqlCeCommand(sql, connection) Dim dr As SqlCeDataReader= cmd.ExecuteReader() While dr.Read ListBox1.Items.Add(dr(1)) End While
当从命令对象创建读取器时,使用第二个列 (dr(1)) 向列表框 (ListBox1) 中添加行。
在 C# 中,代码如下所示。
string sql = "SELECT* FROM Customers"; SqlCeCommandcmd = new SqlCeCommand(sql, connection); SqlCeDataReaderdr = cmd.ExecuteReader();
在 ADO CE 中,唯一受支持的执行不返回任何数据的命令的方式是使用 Connection 对象上的 Execute 方法,然后通过使用以下代码忽略返回值。
connection.Execute("DELETE Customers WHERE CustomerID=1")
在 Visual Basic .NET 中,您可以使用 SqlCeCommand 对象执行命令,如下所示。
Dim cmd As SqlCeCommand= connection.CreateCommand() cmd.CommandText = "DELETE Customers WHERE CustomerID=1" cmd.ExecuteNonQuery()
在 C# 中,代码如下所示。
SqlCeCommandcmd = connection.CreateCommand(); cmd.CommandText = "DELETE Customers WHERE CustomerID=1"; cmd.ExecuteNonQuery();
您还可以通过向构造函数提供命令文本和连接来创建命令对象。
该命令对象具有 ExecuteScalar 方法,当您只需要返回单个值时,可以使用该方法。如果该命令只返回一个带有一个列的行,则您可以使用以下代码。
Dim cmd As SqlCeCommand= connection.CreateCommand() cmd.CommandText = "SELECTCOUNT(*) FROM Customers" Dim numberOfCustomers As Integer = cmd.ExecuteScalar()
在 C# 中,代码如下所示。
SqlCeCommandcmd = connection.CreateCommand(); cmd.CommandText = "SELECTCOUNT(*) FROM Customers"; int numberOfCustomers = (int)cmd.ExecuteScalar();
该命令对象还支持参数(但是,它不支持命名参数),您可能发现这在多次使用命令时非常有用,因为参数化查询避免了重复计算查询计划的需要,因而显著提高了多次发出的命令的总体性能。
您还可以用 ADO CE 中的 Connection 对象上的 Execute 方法,通过使用 SQL insert、update 和 delete 命令来执行数据操作。您可以用 ADO.NET 中的 SqlCeCommand 对象,通过使用上述命令来操作数据,从而获得良好的性能。但是,您必须手动处理 SQL 语法,这有时可能不太方便。ADO CE 和 ADO.NET 都已经轻松地使用结构来执行数据操作。
在 ADO CE 中,您需要以特定的方式打开 Recordset,以便进行数据操作。您提供的命令可能只包含一个表名,并且您需要提供最后一个特定参数。下面是一个在 ADO CE 中添加、更新和删除行的代码示例。
Dim rs As ADOCE.Recordset Set rs = CreateObject("ADOCE.Recordset.3.1") rs.Open "Customers", connection, adOpenDynamic, _ adLockOptimistic, adCmdTableDirect ' INSERT rs.AddNew rs("CustomerID").Value = 1 rs("CompanyName").Value = "My Company" rs.Update ' UPDATE rs.Find "CustomerID=2" rs("CompanyName").Value = "Modified Name" rs.Update ' DELETE rs.Find "CustomerID=3" If Not rs.EOF Then rs.Delete rs.Close
应用程序用直接表操作 (adCmdTableDirect) 的参数打开一个包含 Customers 表的 Recordset。然后,您可以通过使用用于添加新行 (AddNew)、更新已添加或已更改的行 (Update) 和移除行 (Delete) 的 Recordset 内置功能来操作数据。
Visual Basic .NET 中的相应代码如下所示。
Dim da As New SqlCeDataAdapter("SELECT* FROM Customers", _ connection) Dim cb As New SqlCeCommandBuilder(da) da.InsertCommand = cb.GetInsertCommand() da.UpdateCommand = cb.GetUpdateCommand() da.DeleteCommand = cb.GetDeleteCommand() Dim ds As DataSet= New DataSet da.Fill(ds, "Customers") ' INSERT Dim dr As DataRow = ds.Tables("Customers").NewRow() dr("CustomerID") = 1 dr("CustmerName") = "My Company" ds.Tables("Customers").Rows.Add(dr) ' UPDATE dr = ds.Tables("Customers").Select("CustomerID=2")(0) dr("CustomerName") = "Modified Name" ' DELETE dr = ds.Tables("Customers").Select("CustomerID=3")(0) dr.Delete() da.Update(ds, "Customers")
这里,应用程序首先通过向构造函数传递 select 命令和连接,初始化一个新的 SqlCeDataAdapter。您可以使用 SqlCeCommandBuilder 对象,根据数据适配器中的 select 命令生成需要的数据操作命令(insert、update 和 delete)。然后,这些命令在数据适配器中得到设置;稍后,当需要在数据库中保存对 DataSet 中的行所做的更改时,数据适配器将使用这些命令来操作数据。请注意 ADO.NET 模型是如何通过数据适配器达到更高的断开程度的;它充当完全断开的 DataSet 和数据库之间的智能链接。DataSet 不需要任何指向数据库的连接,并且当您用数据填充 DataSet 以后,您可以关闭数据适配器。然后,您可以操作 DataSet;当您完成该操作以后,您可以创建一个新的数据适配器来更新数据库。由于有了新的数据操作模型,因此通过 ADO.NET 可以完成的工作比通过 ADO CE 可能完成的工作多得多。
在 C# 中,相同的代码如下所示。
SqlCeDataAdapterda = new SqlCeDataAdapter( "SELECT* FROM Customers", connection); SqlCeCommandBuildercb = new SqlCeCommandBuilder(da); da.InsertCommand = cb.GetInsertCommand(); da.UpdateCommand = cb.GetUpdateCommand(); da.DeleteCommand = cb.GetDeleteCommand(); DataSetds = new DataSet(); da.Fill(ds, "Customers"); // INSERT DataRow dr = ds.Tables["Customers"].NewRow(); Dr["CustomerID"] = 1; Dr["CustomerName"] = "My Company"; ds.Tables["Customers"].Rows.Add(dr); // UPDATE dr = ds.Tables["Customers"].Select("CustomerID=2")[0]; dr["CustomerName"] = "Modified Name"; // DELETE dr = ds.Tables["Customers"].Select("CustomerID=3")[0]; dr.Delete(); da.Update(ds, "Customers");
迄今为止,本文已经讨论了读取和操作数据的方式。接下来,本文将讨论两个数据库中间件实现中的 SQL 支持中的一些差异。实际上,ADO CE 在以前的工具中实现了 SQL 支持,而即使 ADO.NET 对 SQL 有一些支持,SQL Server CE 本身也支持大多数 SQL 语法。
作为 Pocket PC 程序员,您很快就会发现新工具中 SQL 支持的丰富性 — 包括 SQL 的数据操作语言 (DML) 和数据定义语言 (DDL) 这两个部分。例如,在 ADO CE 中,当您需要知道表中的行数时,您必须打开一个带有从该表中加载的所有实际行的 Recordset 对象。在 ADO.NET 中,您可以简单地查询数据库表的行数 (SELECT COUNT(*) FROM Customers),并且在单个值中获得结果(通过 SqlCeCommand 对象上的 ExecuteScalar 方法)。
为了帮助您直观地了解新工具对于 SQL 的扩展支持,图 1 列出了 ADO CE 和 SQL Server CE 中的保留字。
图 1. ADO CE 和 SQL Server CE 中的 SQL 保留字。
左边一列包含 ADO CE 中的保留字,右边的六个列包含 SQL Server CE 中的保留字。有关详细信息,请浏览 SQL Reference in the SQL Server CE Helpfile(称为联机图书),或者浏览 Visual Studio .NET Help 中的这一内容。
从 eMbedded Visual Basic 迁移到 Visual Basic .NET 和 C#
Moving from eMbedded Visual Basic to Visual Basic .NET 一文讨论了有关从 eMbedded Visual Basic 迁移到 Visual Basic .NET 的大多数常规问题。该文章的“Working with Databases”部分包含的示例代码描述了在使用 SQL Server CE 时,如何将代码从 eMbedded Visual Basic 迁移到 Visual Basic .NET。
它介绍了 Visual Basic .NET 和 C# 这两个版本的迁移代码。这样做的主要原因是让更多身为开发人员的读者能够立即从示例代码中受益。而且,如果您是传统的 eMbedded Visual Basic 开发人员并且要开始使用 .NET Compact Framework,则您还应该考虑 C#。考虑 C# 的主要原因是:在 .NET 中有如此之多的新功能,以至于您可能发现可以使用它来获得一个全新的开始,而无需使用 Visual Basic 遗产。
同步
很多以前的 Pocket PC 应用程序借助于 ActiveSync 同步桌面计算机和设备的数据。ActiveSync 包含一些支持,以便您同步数据库以及选择要在同步操作中包括的表。在 ActiveSync 中,不包含对于将 Microsoft Access 或 SQL Server 2000 数据库与设备上的 SQL Server CE 数据库进行同步的固有支持。但是,您可以使用 ActiveSync 使设备可以借助于传递连接来连接到桌面计算机。
对于 SQL Server CE,您需要使用不同的模型。SQL Server 2000 将同步功能作为 Web 服务器的插件予以支持。在 SQL Server CE Server Tools 安装过程中,在 Internet 信息服务 (IIS) 中设置了一个虚拟目录。该虚拟目录包含一个称为 SQL Server CE Server Agent 的文件 (sscesa20.dll),您可以通过 HTTP 请求来调用它,以便与 SQL Server 2000 同步数据。在客户端,可以使用 SQL Server CE Client Agent,它包含用于合并复制(设置数据订阅)和远程数据访问 (RDA) 的功能。有关合并复制的详细信息,请参阅 SQL Server CE Help(联机图书);该文章集中讨论了如何通过使用 RDA 来同步数据。
即将问世的示例(本文中的大多数代码示例都以它为基础)使用一个源自 Access 的数据库。Access 数据库被逐个表地导出到 SQL Server 2000,而 Access 中提供的功能被导出到 ODBC 数据源 — 在本例中,为 SQL Server 2000 数据库。(有关如何导出 Access 数据库的详细信息,请参阅 Access 帮助或 How To Convert an Access Database to SQL Server。)下一步是通过使用 RDA 中的 Pull 方法,将表从 SQL Server 2000 下载到 SQL Server CE 数据库,如下面的代码所示。
Dim localDatabase As String = "\MobileSales.sdf" Dim localConnectionString As String = "Data Source=" + localDatabase Dim remoteConnectionString As String = "Provider=sqloledb;" + _ "Data Source=(local);Initial Catalog=MobileSales;" + _ "Integrated Security=SSPI;" Dim tables() As String = New String() {"Customers", "Orders", "Products"} If File.Exists(localDatabase) Then File.Delete(localDatabase) End If Dim engine As New SqlCeEngine(localConnectionString) engine.CreateDatabase() engine.Dispose() Dim rda As New SqlCeRemoteDataAccess() rda.InternetUrl = "http://server/ssce/sscesa20.dll" rda.LocalConnectionString = localConnectionString Dim table As String For Each table In tables Try rda.Pull(table, "SELECT* FROM [" + table + "]", _ remoteConnectionString, _ RdaTrackOption.TrackingOffWithIndexes, "ErrorTable") Catch ex As SqlCeException MessageBox.Show(ex.Message); End Try Next rda.Dispose()
本地连接字符串指向将要创建 SQL Server CE 数据库文件的位置,而远程连接字符串则指向应用程序将从中检索数据的 SQL Server 2000 数据库 (MobileSales)。如果数据库文件已经存在,则应用程序会删除它,然后,应用程序通过使用 SqlCeEngine 对象创建数据库。应用程序设置 RDA (SqlCeRemoteDataAccess) 对象,以指向服务器或桌面计算机中驻留 SQL Server CE Server Agent (sscesa20.dll) 的虚拟目录 (ssce)。应用程序使用表数组将表从 SQL Server 2000 拉到刚刚创建的本地 SQL Server CE 数据库中。
请注意,虚拟目录使用匿名访问,并且,通过指定的连接字符串给予 IIS 中的匿名用户(例如,IUSR_MACHINENAME)访问 SQL Server 2000 中数据库的权利。在实际方案中,虚拟目录很可能需要指定的用户,并且随后在 RDA 对象(在它的 InternetLogin 和 InternetPassword 属性中)上设置凭据。
还要注意,应用程序指定用于下载索引和关闭跟踪的选项 (TrackingOffWithIndexes)。如果指定了跟踪,则应用程序以后可以使用 RDA 对象的 Push 方法将表推送回服务器,以便将更改添加到 SQL Server 2000 数据库中。有关详细信息,请参阅 SQL Server CE Help(联机图书)。
在 C# 中,代码如下所示。
string localDatabase = @"\MobileSales.sdf"; string localConnectionString = "Data Source=" + localDatabase; string remoteConnectionString = @"Provider=sqloledb;" + "Data Source=(local);Initial Catalog=MobileSales;" + "Integrated Security=SSPI;"; string[] tables = new string[] { "Customers", "Orders", "Products" }; if(File.Exists(localDatabase)) File.Delete(localDatabase); using(SqlCeEngineengine = new SqlCeEngine(localConnectionString)) engine.CreateDatabase(); using(SqlCeRemoteDataAccessrda = new SqlCeRemoteDataAccess()) { rda.InternetUrl = "http://server/ssce/sscesa20.dll"; rda.LocalConnectionString = localConnectionString; foreach (string table in tables) { try { rda.Pull(table, "SELECT* FROM [" + table + "]", remoteConnectionString, RdaTrackOption.TrackingOffWithIndexes, "ErrorTable"); } catch (SqlCeExceptionex) { //MessageBox.Show(ex.Message); showErrors(ex); } } }
您也可以不使用上述代码,而是继续与桌面计算机上的 Access 数据库进行同步,或者用另一个数据库进行复制。常规解决方案是在服务器(或桌面计算机)上设置 XML Web 服务。该 Web 服务可以发布方法,以供在数据库中执行数据操作的设备使用。
下面的代码示例从 XML Web 服务(作为 Visual Studio .NET 中的 ASP.NET Web 服务项目创建)中使用原始的 Access 数据库。
<WebMethod> _ Public Function Sync(ByVal newCustomerNames() As String) As DataSet ' Set up connection and data adapter OleDbConnection cn = New OleDbConnection(+ "Provider=Microsoft.Jet.OLEDB.4.0;User ID=Admin;" + "Data Source=C:\Mobile Sales.mdb") cn.Open() ' Set up command and insert new customers Dim cmd As New OleDbCommand( "INSERT INTO Customers (CustomerName) VALUES(?)", cn) cmd.Parameters.Add("?", DbType.String) For Each newCustomerName As String In newCustomerNames cmd.Parameters(0).Value = newCustomerName cmd.ExecuteNonQuery Next ' Get all customers Dim da As New OleDbDataAdapter("SELECT* FROM Customers", cn) Dim ds As DataSet= New DataSet() da.Fill(ds, "Customers") ' Send back all customers Return ds End Function
XML Web 服务方法(Web 方法)采用新客户的名称数组作为参数。在设置了连接和命令对象以后,应用程序使用该数组创建新的客户行。请注意代码是如何使用参数来提高插入多个客户的速度的。还要注意,使用设备上的命令对象(通过 .NET Compact Framework 中的 ADO.NET)完成该操作的语法是非常类似的。然后,应用程序再次查询数据库,并且将所有客户名称(包括新名称)返回到设备。注意这就是同步功能,并且需要将所有客户返回到该设备,因为当该设备断开连接时,其他设备可能已经添加了客户。
在 C# 中,代码如下所示。
[WebMethod] public DataSetSync(string[] newCustomerNames) { // Set up connection and data adapter OleDbConnection cn = new OleDbConnection( + "Provider=Microsoft.Jet.OLEDB.4.0;User ID=Admin;" + @"Data Source=C:\Mobile Sales.mdb"); cn.Open(); // Set up command and insert new customers OleDbCommand cmd = new OleDbCommand( "INSERT INTO Customers (CustomerName) VALUES(?)", cn); cmd.Parameters.Add("?", DbType.String); foreach(string newCustomerName in newCustomerNames) { cmd.Parameters[0].Value = newCustomerName; cmd.ExecuteNonQuery(); } // Get all customers OleDbDataAdapter da = new OleDbDataAdapter( "SELECT* FROM Customers", cn); DataSetds = new DataSet(); da.Fill(ds, "Customers"); // Send back all customers (including new) return ds; }
采用类似的方式,应用程序可以访问任何在服务器上具有 ADO.NET 的符合 OLE DB 的数据源 — 或其他具有自己的托管提供程序的数据库(例如,Oracle)。
Mobile Sales .NET 示例
Mobile Sales .NET 示例演示了如何将用 eMbedded Visual Basic 编写并且使用 ADO CE 访问 Pocket Access 数据库中的数据的应用程序迁移到 .NET Compact Framework,以便它使用 ADO.NET 访问 SQL Server CE 数据库中的数据。该示例随附在 Larry Roof 于 2001 年撰写的文章 Data To Go 中。
Mobile Sales .NET 示例是用 Visual Studio.NET2003 创建的。它由单个窗体组成,如图 2 所示。
图 2. Mobile Sales .NET
其方案是一个访问很多个客户的送货司机。在每个站点,他都会取走一份定单。对于每份定单,他都会选择产品,输入数量,然后点击 Add。如果该司机出了错,则他会选择项行,然后点击 Delete。要保存定单,该司机可以点击 Save this order 菜单命令;然后,他可以接着处理下一份定单。当该司机保存了所有客户定单时,他退出应用程序。该示例的工作方式与原始的 eMbedded Visual Basic 示例 (Data To Go) 相同。
- 发表评论请到:http://bbs.cnitom.com
相关阅读
图文热点
- SQL Server2008行数据和页数据压缩解密
- 本文将为大家介绍SQL Server 2008行数据和页数据的一些处理方法,希望能对DBA的管...
- 如何修改天融信NGFW4000防火墙用户认证数据库
- 本文主要是如何修改天融信NGFW4000防火墙用户认证数据库对象的介绍。...
本类热点