最近发布的Microsoft .NET Compact Framework beta1版包括了SQL Server CE2.0,SQL Server CE将SQL Server 2000扩展到windows CE环境中,同时它提供了与桌面应用程序开发相似的的开发环境。在这篇文章中我将初步介绍SQL CE 以及如何利用Smart Device Extension开发Pocket PC上的应用程序。
这个平台允许Windows CE自携带的应用程序与基于.net的应用程序共存。应用程序的宿主(本身也是一个应用程序)用一个公共运行时语言(CRL Common Language Runtime)的实例来管理代码。通过SDE利用.NET Compact Framework类库在CRL的顶端开发应用程序。
构造一个应用程序样本实例
在这个样本实例中将揭示.NET CF Pocket PC程序设计中要注意的几个方面。我将解释在.NET CF中怎样使用Web Service,怎样使用各种空件,以及怎样构件SQL Server CE数据库。这是一个书店的例子,例子中书店的售货员使用Pocket PC进行查询(在Web Sevice中),并在书店中下订单,这个订单将被提交给本地的SQL Server CE数据库。
Web Sevice
Web Sevice将使用SQL Server2000中携带的Pubs数据库,这样你就可以很容易的在自己的机器上测试代码。
getTitles():
<!--WebService Language="VB" Class="Service1"-->
Imports System
Imports System.Data
Imports System.Data.SqlClient
Imports System.Web.Services
Public Class Service1 : Inherits WebService
_
Public Function getTitles( _
ByVal title As String) As DataSet
' Make the database connection.
Dim conn As New SqlConnection( _
"server=localhost; uid=sa;" & _
"password=; database=Pubs")
' Create the SQL and set the parameter.
Dim sql As String = "SELECT * FROM " & _
"titles WHERE title LIKE @title"
Dim comm As New SqlCommand(sql, conn)
comm.Parameters.Add("@title", _
"%" & title & "%")
' Create a data adapter and data set.
Dim dataAdapter As New SqlDataAdapter(comm)
Dim ds As New DataSet()
' Fill the data set with the query results.
conn.Open()
dataAdapter.Fill(ds, "titles")
conn.Close()
' Return the dataset.
Return ds
End Function
End Class
getTitles()方法获得查询字符串作为输入参数,同时返回数据集。 使用 Visual Studio .NET中的 Smart Device Extension (SDE)
在form第一次运行的时候,首先需要核查Pocket PC是否有包含书店信息的数据库,如果没有,那么就要用SQL Server CE引擎对象创建数据库。由于需要与SQL Server CE建立连接,所以必须使用SQL Server CE Managed Provider,因此第一件事情是引用System.Data.SqlServerCe.dll配置和输入相关的名称空间。
Imports System.Data.SqlServerCe
图3
建立数据库后,就需要创建表,操作表就必须熟悉ADO.NET类库,在这个例子中我们将在SQL Server CE Managed Provider使用类: SqlCeConnection 和 SqlCeCommand类。
'-----conn and ds are defined globally-----
Dim conn As New SqlCeConnection( _
"Provider=Microsoft.SQLServer.OLEDB.CE.1.0;" & _
"Data Source=\My Documents\BookStores.sdf")
Dim ds As DataSet
'------------------------------------------
Sub createStoreDB()
' if database does not exist, create one
If Not File.Exists( _
"\My Documents\BookStores.sdf") Then
Dim sqlEngine As New Engine( _
"Data Source=" & _
"\My Documents\BookStores.sdf")
sqlEngine.CreateDatabase()
Dim cmd As New SqlCeCommand( _
"CREATE TABLE Stores(storeID int " & _
"Primary Key NOT NULL, " & _
"storeName nvarchar(20))", conn)
conn.Open()
cmd.ExecuteNonQuery()
cmd.CommandText = _
"CREATE TABLE Orders(storeID int, " & _
"title_id nvarchar(20), qty int)"
cmd.ExecuteNonQuery()
cmd.CommandText = _
"INSERT INTO Stores (storeID, " & _
"storeName) VALUES (2, " & _
"'Computer BookStore')"
cmd.ExecuteNonQuery()
conn.Close()
End If
End Sub
Sub LoadStores()
conn.Open()
Dim reader As SqlCeDataReader
Dim cmd As New SqlCeCommand( _
"SELECT * FROM Stores", conn)
reader = cmd.ExecuteReader
While reader.Read
cboStoreID.Items.Add( _
reader.Item("storeID"))
End While
conn.Close()
End Sub
这样当表单被载入时,ComboBox控件就填充了书店列表。
图5
当选中Store ID时,就显示他代表的
Private Sub cboStoreID_SelectedIndexChanged( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles cboStoreID.SelectedIndexChanged
conn.Open()
Dim sql As String = _
"SELECT * FROM Stores WHERE storeID=" & _
cboStoreID.Items(cboStoreID.SelectedIndex)
Dim cmd As New SqlCeCommand(sql, conn)
Dim reader As SqlCeDataReader = cmd.ExecuteReader
reader.Read()
lblStoreName.Text = reader.Item("storeName")
conn.Close()
End Sub
Private Sub cmdSearch_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles cmdSearch.Click
Dim ws As New TitlesWS.Service1()
' get the web service
ds = ws.getTitles(txtSearch.Text)
cboResult.DataSource = ds.Tables(0)
cboResult.DisplayMember = "title"
End Sub
实际上当书名被选定后,他更多的信息将显示在label控件上。
Private Sub cboResult_SelectedIndexChanged( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles cboResult.SelectedIndexChanged
' display the information of the
' selected book.
Dim row As DataRow
row = ds.Tables("titles").Rows( _
cboResult.SelectedIndex)
lblTitleID.Text = row.Item("title_id")
lblPrice.Text = "$" & row.Item("price")
txtNotes.Text = row.Item("notes")
End Sub
图6
显然ADD按钮用于增加订单中的数量,因此必须给ADD按钮添加一个单击事件:
Private Sub cmdAdd_Click( ByVal sender As System.Object,ByVal e As System.EventArgs) _
Handles cmdAdd.Click
'---add the title to the stores ORDER table
conn.Open()
Dim sql As String = "INSERT INTO Orders " &_
"(storeID, title_id, Qty) VALUES (" & _
cboStoreID.Items(cboStoreID.SelectedIndex) _
& ",'" & _
lblTitleID.Text & "'," & txtQty.Text & ")"
Dim cmd As New SqlCeCommand(sql, conn)
cmd.ExecuteNonQuery()
MsgBox("Title added for " & lblStoreName.Text, _
MsgBoxStyle.Information, "Orders")
conn.Close()
End Sub
返回消息框证实增加数量。
图7
审核订单
点击第二个tab页显示订单,点击Refresh按钮第一个ListBox控件将显示订单。
Private Sub cmdRefresh_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles cmdRefresh.Click
'---displays the list of stores available
conn.Open()
Dim sql As String = "SELECT * FROM Stores"
Dim cmd As New SqlCeCommand(sql, conn)
Dim reader As SqlCeDataReader = _
cmd.ExecuteReader
'---clears the listbox
cboStoreIDs.Items.Clear()
While reader.Read()
cboStoreIDs.Items.Add( _
reader.Item("storeID"))
End While
conn.Close()
End Sub
当一个书店被选中之后,该书店相应的订单就会显示在第二个Listbox控件中。
Private Sub cboStoreIDs_SelectedIndexChanged( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles cboStoreIDs.SelectedIndexChanged
'---displays the orders of store selected
conn.Open()
Dim sql As String = _
"SELECT * FROM Orders WHERE storeID=" & _
cboStoreIDs.Items(cboStoreIDs.SelectedIndex)
Dim cmd As New SqlCeCommand(sql, conn)
Dim reader As SqlCeDataReader = _
cmd.ExecuteReader()
'---clears the listbox
cboOrders.Items.Clear()
While reader.Read()
cboOrders.Items.Add( _
reader.Item("title_id") & " - " & _
reader.Item("qty") & "-copy(ies)")
End While
conn.Close()
End Sub
另一个问题是,如果你想知道数据表是否被正确的更新了。SQL Server 2.0引入了类一个被称为SQL Server CE查询分析器(SQL Server CE Query Analyzer)的工具,在应用程序第一次引用SQL Server CE Managed Provider时,SDE将把相关文件拷贝到目标设备,SQL Server CE查询分析器可以通过点击Start->SQLCE Query(如下图)调用。
有些时候查询分析器会拒绝工作,这也许只是Beta类产品的自然特性。在很多例子中在仿真器中将软件重新设置即可解决这个问题。一般情况下重新设置软件不会影响数据库,但过于频繁的那么就有可能导致找不到保存的数据库,这时找回他的唯一方式是在Visual Studio .NET中重新编译软件(就像数据库重新创建一样)。