智能设备扩展、SQL Server CE 和我

 

下载 Northwind_mobile.exe
我越来越迷恋上了电视节目了。在你们询问“这家伙是怎么回事?”之类的电子邮件雪片般飞过来之前,我自己先做一番解释。
客观上讲,我知道电视节目的时间长度都是一样的。实际上,我已经算出它们的长度一样。电视可以使我摆脱家里的所有时钟。我将电视节目作为日晷的一种新式日用替代品。Gunsmoke 位于 TVL;它上映时就是午餐时间。Trading Spaces 是 TLC 的一档节目;它播出时就是该去跑步的时间了。Baseball Tonight 是 ESPN 的一档节目;它播出时就该关闭 Pocket PC 结束一天的工作了。
令我感到气恼的是电视节目制作人让特定节目所包含的内容不断在缩水。他们是怎么做的呢?他们播放前几周的精彩镜头,通过这种恶毒手段欺骗观众。我敢断言,一些极有前途的制作人心里很清楚:播放老节目比制作新内容轻松得多。以前只有聪明的孩子才会玩的“瞒天过海”这种把戏现在开始在许多电视节目上出现了。
现在不要让我犯错误。这种手法在工作中有着很好、很实际的应用。请先听我讲解片刻。上司问您这周做了哪些事情,而您就把前几周做的事情都算在内。这会使他们瞎猜。如果他们追着您问您在一个紧急的项目中做了哪些工作,您只需把前几个月做的事情统统倒出来就行了。不断地切换内容(我做了这个,我做了那个),并以电影预告片中的低沉声调表述出来。天啊,这样也许您就真的不必再做新的工作了。而只从已经做的工作中领取薪酬就行了。
关于试图颠覆美国社会基础的行为就到此为止,我们还是继续探讨智能设备扩展 (SDE),并初步介绍如何通过 SQL Server CE (SQLCE) 使用 SDE。
SDE + SQLCE = 移动数据
在我最近一次专栏中,我向您介绍了如何通过 SDE 构建一个简单的 Hello World 应用程序。现在,我知道这种应用程序的市场是极其有限的,要以 $9.95 的价格售出 10,000 份副本是十分困难的。所以这个月我将着重介绍一些比较实用的内容 — 通过 SDE 使用 SQLCE。
在开始介绍之前,我先说明一下,使用 SDE 处理数据与通过 eMbedded Visual Basic? 处理数据的差别很大。如果采用 eMbedded Visual Basic,您可以使用两种类型的数据库 — Pocket Access 和 SQLCE。许多开发人员选择使用 Pocket Access,因为它容易实现,而且与 Microsoft Access 相集成。而 SDE 只支持 SQLCE。在 eMbedded Visual Basic 中,您具有 ADOCE。SDE 提供 ADO.NET。
现在,我将深入分析对 ADO.NET 和 .NET Compact Framework 的一个不切实际的诽谤。不瞒您说,那些类型的文章着实令我头痛。相反,在本文及后续一些文章中,我将通过一些示例向您演示在构建移动应用程序中经常需要用到的一些功能和特性。
SDE 样式的 Northwind Mobile
我将通过一个称为 Northwind Mobile 的简单应用程序来向您介绍 SDE 和 SQLCE。这个应用程序的名称来源于在其上构建它的数据库 — 有名的 Northwind 数据库。我不知道您对它有什么感觉,反正 Northwind 是我最喜欢的数据库。事实上,在网络泡沫膨胀之际,我经营了一家电子商务公司,它提供一组专门处理 Northwind 数据库的服务。这次尝试的收获就是发现公司需要 Northwind 数据库的唯一原因是:它是由 Microsoft 提供的。虽然幸运地拥有这个公司,但它还是破产了,这主要有两个原因:
每个人都已经拥有 Northwind 的副本了。
没有人需要在关键地方使用它。
Northwind Mobile 概述
Northwind Mobile 是一个简单的应用程序。它的唯一功能是显示存储在本地 SQL Server CE 数据库中的定单。它拥有一个客户列表,您可以从中挑选。当您选择客户时,会构建他们的定单列表。从这个列表中选择一个定单可以显示定单的详细信息。图 1 显示了使用中的一个示例 Northwind Mobile 应用程序。

1. Northwind Mobile 应用程序
Northwind Mobile 的界面
Northwind Mobile 界面由七个控件组成:两个 ComboBox、两个 Label、两个 TextBox 和一个 ListView。图 2 显示了 SDE 窗体设计器的界面。

2. Northwind Mobile 界面设计
Northwind Mobile 数据库
我前面已经提到,Northwind Mobile 应用程序使用 SQL Server CE 数据库。事实上,创建数据库也是它的一部分功能。我为什么使用这种方案呢?只是因为它是 SDE 和 SQLCE 入门的最简单途径。是的,我知道 SQLCE 提供了大量功能来从 SQL Server 数据库检索数据。尽管如此,有时您只需要一个本地数据库就可以了。要学会的是如何创建这个数据库。有两种方法:
通过代码创建数据库。
使用 SQLCE Query 工具创建数据库。
我们首先来看通过代码创建数据库这种方法。
通过代码构建数据库
您需要先在项目中添加对 System.Data.SqlServerCe 组件的引用,然后才可以在 SDE 应用程序中使用 SQLCE 数据库。可以这样来实现:在开发环境中,从 Project 菜单中选择 Add Reference…。然后从 Add Reference 对话框中选择 System.Data.SqlServerCe 组件,如图 3 所示。

3. Add Reference 对话框选择 System.Data.SqlServerCe 组件
Northwind Mobile 应用程序中的 CreateDatabase 例程演示了如何通过代码创建数据库。当应用程序启动时就会调用这个例程。
在 CreateDatabase 顶部,可以看到一小块注释代码。我是出于调试目的添加的,并考虑到也许对您有用而决定留下它。它演示了如何检查一个文件是否存在,以及如何删除一个文件。
Private Sub CreateDatabase()    Dim cn As System.Data.SqlServerCe.SqlCeConnection    Dim SQL As String    Dim SQLEngine As System.Data.SqlServerCe.Engine' If the database exists, blow it away.'    If System.IO.File.Exists("\My Documents\Northwind.sdf") Then'      System.IO.File.Delete("\My Documents\Northwind.sdf")'    End If
进行检查是为了确定数据库是否存在。如果不存在,就创建它。此时数据库是空的,因此没有结构或内容。
' If the database does not already exist, then create it.    If Not System.IO.File.Exists("\My Documents\Northwind.sdf") Then      SQLEngine = New System.Data.SqlServerCe.Engine _       ("data source=\My Documents\Northwind.sdf")      SQLEngine.CreateDatabase()
既然数据库已经存在,就可以打开它。
' Next, open the database.      cn = New _        System.Data.SqlServerCe.SqlCeConnection("Provider=Microsoft.SQLServer.O _        LEDB.CE.1.0;Data Source=\My Documents\Northwind.sdf")      cn.Open()
使用一组 SQL CREATE TABLE 语句定义表及其相关字段。这个示例只包含四个原始的 Northwind 表:Customers、Orders、OrderDetails 和 Products。
' Now, through a series of SQL statements create the structure of the database.' Create the Customers table.      SQL = "CREATE TABLE Customers (CustomerID nchar(5) Primary Key _        NOT NULL,CompanyName nvarchar(40) NOT NULL)"      Dim cmd As New System.Data.SqlServerCe.SqlCeCommand(SQL, cn)      cmd.CommandType = CommandType.Text      cmd.ExecuteNonQuery()' Create the Orders table.      SQL = "CREATE TABLE Orders (OrderID int Primary Key NOT _        NULL,CustomerID nchar(5) NOT NULL,OrderDate datetime _        NULL,ShippedDate datetime NULL)"      cmd.CommandText = SQL      cmd.ExecuteNonQuery()' Create the OrderDetails table.      SQL = "CREATE TABLE OrderDetails (OrderID int NOT NULL,ProductID _        int NOT NULL,UnitPrice money NOT NULL,Quantity smallint NOT _        NULL,Discount real NOT NULL)"      cmd.CommandText = SQL      cmd.ExecuteNonQuery()' Create the Products table.      SQL = "CREATE TABLE Products (ProductID int Primary Key NOT _        NULL,ProductName nvarchar (40) NOT NULL)"      cmd.CommandText = SQL      cmd.ExecuteNonQuery()
此时数据库有了基本的结构,但没有数据。我准备使用大量 SQL INSERT 语句对其进行修改,这些语句的作用是将一组测试数据加载到数据库中。再次声明,这些只是原始的 Northwind 数据库中的一部分数据。您可以认为它是 Northwind 简化版。
为了节省空间,对于每个表,我将 SQL INSERT 语句缩减为一条 INSERT 语句。对于那些有兴趣而且有大量时间的读者,可以在文章顶部下载 Northwind Mobile 示例项目,查看所有的 INSERT 语句,并引以为豪。
' Next, through a far greater set of SQL statements load some content into the database.' Load the Customers table.      SQL = "INSERT INTO Customers (CustomerID, CompanyName) VALUES _        ('ALFKI','Alfreds Futterkiste')"      cmd.CommandText = SQL      cmd.ExecuteNonQuery()' Load the Orders table.      SQL = "INSERT INTO Orders (OrderID, CustomerID, OrderDate, _        ShippedDate) VALUES (10643,'ALFKI','1997-08-25 00:00:00', _        '1997-09-02 00:00:00')"      cmd.CommandText = SQL      cmd.ExecuteNonQuery()' Load the OrderDetails table.      SQL = "INSERT INTO OrderDetails (OrderID, ProductID, UnitPrice, _        Quantity, Discount) VALUES (10643,28,45.6,15,0.25)"      cmd.CommandText = SQL      cmd.ExecuteNonQuery()' Load the Products table.      SQL = "INSERT INTO Products (ProductID, ProductName) VALUES (1,'Chai')"      cmd.CommandText = SQL      cmd.ExecuteNonQuery()' Close the database.      cn.Close()    End If  End Sub

使用 SQLCE 查询构建数据库
当您在设备中安装 SQL Server CE 2.0 测试版以及 SQLCE 本身一些零碎的文件之后,您就获得了一个叫做 SQLCE Query 的工具。为方便访问,将它放在了 Start菜单中。通过这个工具,您可以在设备中创建和查询 SQLCE 数据库。现在要承认,由于这个工具要求您使用 SIP(软输入面板),所以它可能让您短寿 5 到 7 年,但如果您有一个 Targus 键盘或者一个桌面实用工具(如 Pocket Controller (http://www.soti.net/)),则它可以工作得很好。这个工具对于调试任何基于 SQLCE 的应用程序很有帮助,并且在必要时可以创建与您的应用程序配套的数据库。图 4 显示了 SQLCE Query 界面的一个示例。

4. SQLCE Query 应用程序
走进 Northwind Mobile
既然我们有了数据库,我将带您走进组成 Northwind Mobile 应用程序的各个例程。
启动应用程序
Northwind Mobile 的加载事件过程执行以下三个功能:
在必要时创建数据库。
设置 ListView 控件的格式。
加载客户列表。
Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As _    System.EventArgs) Handles MyBase.Load' Check to see if the database exists. If it does not exist it will be created.    CreateDatabase()' Format the ListView control.    FormatListView()' Load the Customer combo box.    LoadCustomers()  End Sub
我们已经看过了 CreateDatabase 例程。接下来简要看一下 FormatListView 和 LoadCustomers。
设置 ListView 控件的格式
对 ListView 控件进行一些简单的格式设置,使它具有列标题,并设置列宽。此处也对应用程序要使用的视图 — 详细信息视图进行了格式设置。
Private Sub FormatListView()' This routine handles configuring the listview control.    lvwOrder.View = View.Details    lvwOrder.Columns.Add("Product", 120, HorizontalAlignment.Left)    lvwOrder.Columns.Add("Qty", 40, HorizontalAlignment.Right)    lvwOrder.Columns.Add("Price", 50, HorizontalAlignment.Right)    lvwOrder.Columns.Add("Disc", 50, HorizontalAlignment.Right)    lvwOrder.Columns.Add("Total", 60, HorizontalAlignment.Right)  End Sub
加载客户列表
LoadCustomers 例程让我们初步了解了如何从 SQLCE 数据库检索数据。
Private Sub LoadCustomers()    Dim cn As System.Data.SqlServerCe.SqlCeConnection    Dim cmd As System.Data.SqlServerCe.SqlCeCommandDim dtr As System.Data.SqlServerCe.SqlCeDataReader
首先打开数据库。此处除了指定 Northwind 数据库的位置,还指定了 SQLCE 提供程序。
' Open the database.    cn = New _      System.Data.SqlServerCe.SqlCeConnection("Provider=Microsoft.SQLServer. _      OLEDB.CE.1.0;Data Source=\My Documents\Northwind.sdf")    cn.Open()
SQL SELECT 语句用于检索所有客户,并将结果放在 DataReader 对象中。
' Retrieve a list of the customers.    cmd = New System.Data.SqlServerCe.SqlCeCommand("SELECT * FROM Customers", cn)    dtr = cmd.ExecuteReader()
DataReader对象的功能很像一个只进、只读的记录集。它允许您单向遍历一组记录,并专门为加载 ComboBox 而设计的。
' Load the list into the customer combo box.    cmbCustomers.Items.Clear()    While dtr.Read()      cmbCustomers.Items.Add(dtr("CompanyName"))    End While
当我们关闭数据库对象并从 ComboBox 中选择第一个客户时,LoadCustomers 例程就执行完毕。选择第一个客户会初始化一连串事件,这些事件会加载客户的定单并显示其中一个。
' Clean-up.    dtr.Close()    cn.Close()' Select the first customer.  cmbCustomers.SelectedIndex = 0  End Sub
加载定单列表
选择一个客户就会加载该客户的定单列表。这是由 LoadOrders 例程执行的。从功能上讲,这个例程与 LoadCustomers 很相似,但比 SQL SELECT 语句略微有些复杂,它演示了 SQL Server CE 对 SQL INNER JOIN 语句的支持。
Private Sub LoadOrders()    Dim cn As System.Data.SqlServerCe.SqlCeConnection    Dim cmd As System.Data.SqlServerCe.SqlCeCommand    Dim dtr As System.Data.SqlServerCe.SqlCeDataReader    Dim SQL As String' Open the database.    cn = New System.Data.SqlServerCe.SqlCeConnection("Provider=Microsoft.SQLServer. _  OLEDB.CE.1.0;Data Source=\My Documents\Northwind.sdf")    cn.Open()' Retrieve the orders for the selected customer.    SQL = "SELECT Orders.OrderID FROM Orders INNER JOIN Customers ON "    SQL = SQL & "Orders.CustomerID = Customers.CustomerID WHERE "    SQL = SQL & "(Customers.CompanyName = '" & cmbCustomers.Text    SQL = SQL & "')"    cmd = New System.Data.SqlServerCe.SqlCeCommand(SQL, cn)    dtr = cmd.ExecuteReader()' Load the list into the order combo box.    cmbOrders.Items.Clear()    While dtr.Read()      cmbOrders.Items.Add(dtr("OrderID"))    End While' Clean-up.    dtr.Close()    cn.Close()  End Sub
加载定单详细信息
当选择一个定单时,就会首先从 SQLCE 数据库检索该定单的详细信息,然后加载到 ListView 控件中。这些功能是由 LoadOrderDetails 例程执行的。与 LoadCustomers 和 LoadOrders 例程一样,LoadOrderDetails 例程的核心内容包含两条 SQL SELECT 语句。一条用于捕获定单的摘要信息,另一条用于恢复选定的定单所包含的各个项目。
Private Sub LoadOrderDetails()    Dim cn As System.Data.SqlServerCe.SqlCeConnection    Dim cmd As System.Data.SqlServerCe.SqlCeCommand    Dim Discount As Single    Dim dtr As System.Data.SqlServerCe.SqlCeDataReader    Dim ItemTotal As Single    Dim LVItem As ListViewItem    Dim OrderTotal As Single    Dim Quantity As Int16    Dim SQL As String    Dim UnitPrice As Single' Open the database.    cn = New System.Data.SqlServerCe.SqlCeConnection("Provider=Microsoft.SQLServer._  OLEDB.CE.1.0;Data Source=\My Documents\Northwind.sdf")    cn.Open()' Retrieve the order summary information.    SQL = "SELECT OrderDate, ShippedDate FROM Orders WHERE "    SQL = SQL & "OrderID = " & cmbOrders.Text    cmd = New System.Data.SqlServerCe.SqlCeCommand(SQL, cn)    dtr = cmd.ExecuteReader()    dtr.Read()    txtOrdered.Text = dtr("OrderDate")    txtShipped.Text = dtr("ShippedDate")    dtr.Close()' Retrieve the order details for the selected order.    SQL = "SELECT OrderDetails.UnitPrice, OrderDetails.Quantity, "    SQL = SQL & "OrderDetails.Discount, Products.ProductName FROM OrderDetails "    SQL = SQL & "INNER JOIN Products ON "    SQL = SQL & "OrderDetails.ProductID = Products.ProductID WHERE "    SQL = SQL & "OrderDetails.OrderID = " & cmbOrders.Text    cmd = New System.Data.SqlServerCe.SqlCeCommand(SQL, cn)dtr = cmd.ExecuteReader()
与使用 eMbedded Visual Basic 的情况一样,SDE ListView 控件不能很直观地处理。下面可以看到这个过程:首先创建一个新项,添加到列表中;然后将各个值加载到此项中;最后是如何将该项添加到 ListView 控件中。
' Load the order details into the ListView control.    lvwOrder.Items.Clear()    While dtr.Read()      LVItem = New ListViewItem()      LVItem.Text = dtr("ProductName")      Quantity = dtr("Quantity")      LVItem.SubItems.Add(Quantity.ToString)      UnitPrice = dtr("UnitPrice")      LVItem.SubItems.Add(UnitPrice.ToString("N2"))      Discount = dtr("Discount")      LVItem.SubItems.Add(Discount.ToString("N2"))      ItemTotal = Quantity * UnitPrice * Discount      OrderTotal = OrderTotal + ItemTotal      LVItem.SubItems.Add(ItemTotal.ToString("N2"))      lvwOrder.Items.Add(LVItem)    End While
这样就在 ListView 控件中添加了完整的一行,从而完成定单详细信息的显示。
' Add the total for the order.    LVItem = New ListViewItem()    LVItem.Text = "TOTAL"    LVItem.SubItems.Add("")    LVItem.SubItems.Add("")    LVItem.SubItems.Add("")    LVItem.SubItems.Add(OrderTotal.ToString("N2"))    lvwOrder.Items.Add(LVItem)' Clean-up.    dtr.Close()    cn.Close()  End Sub
不用的代码
这是 Geraldo Rivera 类型的一种情况。如果您正好是一个代码狂,宁愿浏览代码源也不愿阅读我的文章,您会在 Northwind Mobile 应用程序中找到一个名为 ApplicationLocation 的例程。事实上有趣的是,ApplicationLocation 这个例程什么用处都没有。我从没有以任何方式调用它或引用它。
为什么我要包含它呢?我想向您说明如何在 SDE 中获得与 eMbedded Visual Basic App.Path 等效的语句。在 Northwind Mobile 应用程序中,我在 My Documents 文件夹中创建 Northwind 数据库。在您的应用程序中,您可能需要在驻留应用程序的同一个文件夹中创建一个数据库或者另外创建一个文件。因此这就需要用到 ApplicationLocation。这个示例也能表明有些事情在 SDE 中完成比在 eMbedded Visual Basic 中完成来得复杂。
Private Function ApplicationLocation() As String' Fetch and return the location where the application was launched.    ApplicationLocation = _      System.IO.Path.GetDirectoryName(Reflection.Assembly. _      GetExecutingAssembly().GetName().CodeBase.ToString())  End Function
Northwind Mobile 摘要
我构建 Northwind Mobile 有两个目的。其一是向您介绍如何通过代码创建 SQLCE 数据库。虽然您不会总是使用这种方法,但当您构建的应用程序没有包含后端 SQL Server 数据库时,这种方法正好可以派上用场。其二是让您知道通过 SDE 使用 SQLCE 数据库十分简单。通常都说 SQLCE 很难使用,很大程度是因为从 SQL Server 数据库检索数据比较复杂。这个应用程序也表明,并不一定需要这样做。
应该意识到,我只是介绍 SDE 的数据访问,这只是它提供的功能中很简单的一部分。还有很多内容有待挖掘。
开始进行 SDE 开发
想要在一周内速成 SDE 吗?我的培训可以帮您实现这个愿望。我提供了为期五天的 SDE 培训班,它为您提供了要速成所需掌握的一切知识。我会向您介绍如何使用 SDE、SQL Server CE 和 XML 创建健壮的移动解决方案。要获得详细提纲,请访问 www.larryroof.com
返回原路
这就是本月的话题。我已经准备好了紧身潜水衣和跳板准备出发了。报告来自 Huntington Beach,而且不断在增长。下次我将向您介绍使用 SDE 和 SQLCE 的更好方式。到那时候,我就返回了原路。
John Kennedy 白天是 Visual C++ 小组中的一名技术作者和编程人员,晚上则是过着秘密生活的 Pocket PC 开发人员。
Larry Rooflarryroof.com的首脑,该公司专门从事移动项目咨询,以及针对 eMbedded Visual Basic、智能设备扩展和 SQL Server CE 的培训。

posted @ 2008-11-25 18:16  googlegis  阅读(241)  评论(0编辑  收藏  举报

坐标合肥,非典型GIS开发人员 GitHub