65.9K
CodeProject 正在变化。 阅读更多。
Home

Silverlight 3:显示 SQL Server 数据

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.83/5 (26投票s)

2009年9月15日

CPOL

17分钟阅读

viewsIcon

185370

downloadIcon

4936

本文演示了如何在 Silverlight DataGrid 中显示 SQL Server 数据。

引言

Silverlight 3 是迄今为止最棒的 Web 编程技术!我对 Silverlight 3 感到非常兴奋!我希望在这里与您分享一些有助于您快速上手 Silverlight 3 和 SQL Server 数据库的内容。

本文将引导您完成在 Silverlight 3 应用程序中显示 SQL Server 数据库数据的过程。

本示例将使用三种技术:SQL Server、Windows Communication Foundation (WCF) 和 Silverlight 3,它运行在 Visual Studio 2008 中。

背景

我认真考虑过是否要发布这篇文章,因为我知道网上已经有很多关于这个主题的优秀文章,例如

我实际上研究过我找到的一些文章,但在一些不太清晰的领域遇到了困难。我决定添加这篇文章,因为我觉得我可以提供另一种视角,并为初学者 Silverlight 开发人员增加一些可能更有帮助的细节。我希望如此!我已尽力捕捉所有细节并为您提供分步示例。

此外,只是一个不请自来的推荐,我也会在我的博客上发布这篇文章:Silverlight 3:显示 SQL Server 数据

设置...

在开始之前,让我们确保我们设置好了以下各项

SQL Server

首先,您必须在计算机上安装 SQL Server 或 SQL Express。既然您已经开始阅读这篇文章,我猜您已经安装了。但是,如果您没有,请按照此链接下载和安装 SQL Express:http://www.microsoft.com/Sqlserver/2005/en/us/express.aspx

AdventureWorks 数据库

接下来,您需要下载 AdventureWorks 数据库并将其安装到 SQL Server 中。有关如何执行此操作的说明,请访问此链接:http://msdn.microsoft.com/en-us/library/aa992075(VS.80).aspx

Silverlight 3

此外,您必须安装 Silverlight 3。Silverlight 3 在 Visual Studio 2008 中运行。要安装 Silverlight 3,请访问以下链接:http://silverlight.net/getstarted/silverlight3/default.aspx

创建项目...

首先,启动 Visual Studio 2008 并创建一个新项目(文件菜单 | 新建 | 项目…)。

在左侧的“项目类型”树状视图中,在“Visual Basic”节点下,单击“Silverlight”节点,然后在右侧选择“Silverlight 应用程序”模板。将项目命名为“AdventureWorks”。确保已选择“.NET Framework 3.5”。完成后单击“确定”。

这是我的样子

单击“确定”按钮后,应会打开“新建 Silverlight 应用程序”窗口。在此,我们将被提示选择是创建新的 ASP.NET Web 站点项目,还是创建用于托管 Silverlight 应用程序的 ASP.NET Web 应用程序项目。我们将保留选中“ASP.NET Web 应用程序项目”,但将“新建 Web 项目名称”从“AdventureWorks.Web”更改为“AdventureWorks_WebServer”,以使其更清晰。完成后单击“确定”按钮。

这是我的样子

单击“确定”按钮后,Visual Studio 将创建一个包含“AdventureWorks_WebServer”ASP.NET Web 服务器应用程序的解决方案,它将作为“AdventureWorks”Silverlight 客户端应用程序(也已创建)的测试环境。

查看解决方案资源管理器,您会发现以下内容

在 AdventureWorks Silverlight 客户端应用程序中,有两个 .xaml 文件:一个 App.xaml 文件,用于声明资源;以及 MainPage.xaml 文件,这是应用程序启动时加载的默认用户控件。MainPage.xaml 文件是我们稍后用于设计界面的文件。

在 AdventureWorks_WebServer 应用程序中,以下四个文件中的任何一个都可以用于托管 Silverlight 应用程序

  • AdventureWorksTestPage.aspx
  • AdventureWorksTestPage.html
  • Default.aspx
  • Silverlight.js

AdventureWorksTestPage.aspx 文件是应用程序运行时加载的默认启动页面,它将托管 MainPage.xaml 用户控件。

此示例中的 AdventureWorksTestPage.html 文件、Default.aspx 文件和 Silverlight.js 文件都可以删除,因为它们不会被使用。

Web.config 文件用于存储 Web 服务器的配置信息。我们稍后将详细了解这一点。

创建 AdventureWorks 连接...

如果您已经安装了 SQL Server 并附加了 AdventureWorks 数据库,那么您就可以继续创建连接了。

在 Visual Studio 中,单击“工具”菜单 | “连接到数据库…”。“添加连接”窗口将打开并准备好进行配置。确保“数据源”设置为“Microsoft SQL Server (SqlClient)”。将服务器名称设置为“localhost”(如果您将数据库附加到 SQL Server)或“localhost\SQLExpress”(如果您将数据库附加到 SQL Express)(如果您更改了实例名称而不是默认值,请务必指定该名称,而不是“SQLExpress”)。最后,选择“AdventureWorks”数据库。完成后单击“确定”按钮。

这是我的样子

现在我们已经创建了连接,我们将创建一个 LINQ to SQL 类并将其配置为使用 AdventureWorks 数据库。

添加 LINQ to SQL 类...

由于我们刚刚在服务器资源管理器中创建了到 SQL Server AdventureWorks 数据库的连接,因此我们将向应用程序添加一个 LINQ to SQL 类,该类将用于存储连接信息,并从 Person.Contact 表检索数据。

要执行此步骤,请右键单击 AdventureWorks_WebServer 项目,然后选择“添加” | “新建项…”。当“添加新项”窗口打开时,单击“数据”节点,然后在右侧选择“LINQ to SQL 类”模板。将名称保留为“DataClasses1.dmbl”,然后单击“添加”按钮。

这里有一个例子:

单击“添加”按钮后,“DataClasses1.dbml”文件将添加到 AdventureWorks_WebServer 项目中,并将在解决方案资源管理器中显示。如果它没有自动打开,请双击它以打开设计器。

接下来,确保服务器资源管理器已打开(视图菜单 | 服务器资源管理器)。然后,展开“AdventureWorks”数据库节点,并展开“表”节点。找到“Contact (Person)”表,左键单击它,然后将其从服务器资源管理器拖到 DataClasses1.dbml 设计器,如下所示

成功将 Contact 表添加到 DataClasses1.dbml 后,保存项目(文件菜单 | 全部保存)。然后,关闭 DataClasses1.dbml 设计器,因为我们已完成此操作。

添加 ContactRecord 类...

从上面的 Contact 表可以看出,有很多信息!有很多列,例如:ContactID、NameStyle、Title 等。由于我们只想要 FirstName、LastName 和 EmailAddress 列,因此我们将创建一个自定义 ContactRecord 类来表示表中的每个联系人行,而不是使用暴露的 Contact 类型。

注意,我首先想到的是,为什么不直接使用 ADO.NET?DataSets 和 DataTables 要容易处理得多!虽然这是真的,但 WCF 的设计遵循 SOA 原则,这意味着我们需要针对契约进行编程,而不是实现。由于 DataSets 和 DataTables 是 .NET 特定的类型,因此我们不能使用它们。虽然它们可以在 WCF 服务中使用,但不能传递给 Silverlight。

要创建 ContactRecord 类,请在解决方案资源管理器中右键单击 AdventureWorks_WebServer 项目节点,选择“添加” | “类…”。将其命名为“ContactRecord.vb”,然后单击“添加”按钮。

添加类后,为其添加三个公共成员:FirstNameLastNameEmail。我们的类现在应该如下所示

Public Class ContactRecord
    Public FirstName As String
    Public LastName As String
    Public Email As String
End Class 

保存项目(文件菜单 | 全部保存)。接下来,我们将查看添加 WCF 服务。

添加 WCF...

现在我们已经设置了 LINQ to SQL 类,并创建了 ContactRecord 类,我们可以向 AdventureWorks_WebServer 项目添加一个 Windows Communication Foundation 类了。该类将充当一个服务,该服务将使用 LINQ to SQL 类从 AdventureWorks 数据库检索数据,并将其返回给 Silverlight 客户端应用程序。

在解决方案资源管理器中,右键单击 AdventureWorks_WebServer 项目节点,然后选择“添加” | “新建项…”。单击“Silverlight”节点,然后选择“Silverlight 启用的 WCF 服务”模板。将其命名为“Service1.svc”并单击“添加”按钮。

这是我的样子

添加 WCF 服务后,您会在 AdventureWorks_WebServer 项目节点下找到一个“Service1.svc”文件。如果它没有自动打开,请双击它以打开代码窗口。

代码窗口现在应该如下所示

Imports System.ServiceModel
Imports System.ServiceModel.Activation

<ServiceContract(Namespace:="")> _
<AspNetCompatibilityRequirements( _
    RequirementsMode:= _
    AspNetCompatibilityRequirementsMode.Allowed)> _
Public Class Service1

    <OperationContract()> _
    Public Sub DoWork()
        ' Add your operation implementation here
    End Sub

    ' Add more operations here and mark them 
    '  with <OperationContract()>

End Class

我们将对此服务进行几项操作

  • ServiceContract 添加命名空间。这将确保我们的自定义类型是唯一的。
  • 请注意,命名空间应该是一个 URI,但实际上不必指向 Web 上的真实位置。它仅用作自定义类型的唯一标识符。

  • 删除类中的所有代码和注释。

添加 GetContacts 函数

现在我们可以添加我们自己的 GetContacts() 函数了,它将从 Silverlight 客户端应用程序调用。添加此函数时,将返回类型声明为 List(Of ContactRecord),并确保在函数名称上方添加 <OperationContract()> 属性。这使得该函数可供 Silverlight 客户端访问。

添加命名空间和 GetContactions() 函数后,代码窗口应如下所示

Imports System.ServiceModel
Imports System.ServiceModel.Activation

<ServiceContract(Namespace:="http://adventureworks.com/")> _
<AspNetCompatibilityRequirements( _
    RequirementsMode:= _
    AspNetCompatibilityRequirementsMode.Allowed)> _
Public Class Service1

    <OperationContract()> _
    Public Function GetContacts() _
        As List(Of ContactRecord)

    End Function

End Class

向 GetContacts 函数添加代码

GetContacts() 函数中,我们可以使用我们添加的“DataClasses1.dbml”LINQ to SQL 类,当然还有 LINQ,来访问 AdventureWorks 数据库的 Contact 表中的数据。将前 1000 行添加到列表中,然后返回它。

这是我们的函数的样子

<OperationContract()> _
Public Function GetContacts() As List(Of ContactRecord)

    'Use the LINQ to SQL Class to access
    '  the Contact table in the Adventure-
    '  Works database.
    Dim db As New DataClasses1DataContext()

    'Use LINQ to retrieve the rows from the
    '  Contact table.
    '  Notice that the ".Take(1000)" method
    '  returns the first (top) 1000 rows 
    '  of the result set.
    Dim contacts = _
        (From contact _
        In db.Contacts _
        Order By contact.FirstName, _
            contact.LastName _
        Select contact).Take(1000)

    'Create a new generic list of Contact-
    '  Record type.  This list will be
    '  returned to the Silverlight client
    '  application.
    Dim list As New List(Of ContactRecord)

    'Loop through each row of the Contact
    '  table and add it to the list.
    For Each c In contacts

        list.Add( _
            New ContactRecord With _
                 {.FirstName = c.FirstName, _
                  .LastName = c.LastName, _
                  .Email = c.EmailAddress})

    Next

    'Return the list
    Return list

End Function 

接下来,保存项目(文件菜单 | 全部保存)。

更新 Web.config 文件...

我们添加的 WCF 服务使用 Web.config 文件来访问配置信息。它需要检索的配置信息包括 地址绑定契约,您会在 <endpoint> 标签中找到。

在解决方案资源管理器中找到“Web.config”文件,然后双击它以打开。打开后,向下滚动到 <services> 部分。这是我 web.config 文件中的 services 部分的样子

<service behaviorConfiguration=
    "AdventureWorks_WebServer.Service1Behavior"
    name="AdventureWorks_WebServer.Service1">
    
    <endpoint address="" binding="customBinding" 
        bindingConfiguration="customBinding0"
        contract="AdventureWorks_WebServer.Service1" />
    
    <endpoint address="mex" 
        binding="mexHttpBinding" 
        contract="IMetadataExchange" />
    
</service> 

请注意,有两个 endpoint 标签:上面的标签具有 address=””,下面的标签具有 address=”mex”。我们将重点关注上面的标签,其 address=””,如下所示

<endpoint address="" binding="customBinding" 
    bindingConfiguration="customBinding0"
    contract="AdventureWorks_WebServer.Service1" /> 

为了与 Silverlight 客户端应用程序成功通信,我们需要将绑定更改为“basicHttpBinding”,并删除 bindingConfiguration,如下所示

<endpoint address="" binding="basicHttpBinding" 
    contract="AdventureWorks_WebServer.Service1" />

进行这些更改后,保存项目(文件菜单 | 全部保存),然后关闭 web.config 文件。

好的,现在我们已经设置好了连接、添加了 LINQ to SQL 类、创建了 ContactRecord 类、编写了 WCF 服务,并更新了 web.config 文件……所以我们准备开始处理 Silverlight 客户端界面了。

向 Silverlight 客户端添加服务引用...

现在到了激动人心的部分!我们开始处理 Silverlight 3 了!

查看解决方案资源管理器,然后进入 AdventureWorks Silverlight 客户端应用程序,如下所示

我们首先要做的就是添加对我们之前创建的 WCF 服务的引用。这将使我们的 Silverlight 客户端应用程序能够与我们之前创建的 WCF 服务进行通信。为此,请右键单击 AdventureWorks 项目节点,然后选择“添加服务引用…”,如下所示

单击菜单项后,“添加服务引用”窗口将打开。打开后,执行以下步骤

  • 单击“发现”按钮以查找服务的地址。
  • 在“服务”树状视图中,您应该看到列出的服务。
  • 展开“Service1.svc”节点。
  • 展开“Service1”节点。
  • 单击最后一个“Service1”子节点。
  • 您应该能在右侧的“操作”列表视图中看到“GetContacts”方法。

这是我看到的样子

如果在单击“发现”按钮后,您没有看到 Service1.svc 服务列表,请返回 web.config 文件并确保您已按上述说明正确配置。请务必删除 addressbindingcontract 属性及其值之间的任何不必要空格。

接下来,单击“高级…”按钮以显示“服务引用设置”窗口。在这里,我们需要将“集合类型”更改为 System.Collections.Generic.List,如下所示

更改集合类型后,单击“确定”按钮关闭“服务引用设置”窗口,然后再次单击“确定”关闭“添加服务引用”窗口。

现在您应该能在解决方案资源管理器中看到我们添加的新服务引用了

我们稍后将使用服务引用。

编程界面...

现在一切就绪了!我们最后需要做的是编写 Silverlight 客户端应用程序的界面,然后添加必要的 Visual Basic 代码来检索数据并将其显示在我们的界面上。

在解决方案资源管理器中,找到 MainPage.xaml 文件并双击它。这将会在 XAML 编辑器中打开该文件。

一旦 MainPage.xaml 文件在 XAML 编辑器中打开,您会注意到它是一个 UserControl。这显而易见,只需查看开头的 <UserControl> 和结束的 </UserControl> 标签。如前所述,AdventureWorksTestPage.aspx 是应用程序运行时加载的启动 Web 页,但其中嵌入了 MainPage.xaml 用户控件。我们在 MainPage.xaml 用户控件中编写的界面是程序运行时 Web 页上实际显示的界面。

配置主网格

首先,找到 <Grid 标签并添加一个 Margin 属性,将其设置为 10。这将为用户控件的所有四个边缘提供 10 的边距。此外,设置 ShowGridLines=”True”,以便在我们编写界面时显示网格线。我们稍后会将其删除,但现在,它将让我们在工作时看到网格。

<Grid x:Name="LayoutRoot" 
      Margin="10" ShowGridLines="True" >
</Grid> 

接下来,我们将界面分成两部分:顶部的标题部分和占据页面其余部分的数据部分。为此,请将 Grid 配置为具有一列和两行

<Grid x:Name="LayoutRoot" 
      Margin="10" ShowGridLines="True" >

      <Grid.ColumnDefinitions>
          <ColumnDefinition Width="*" />
      </Grid.ColumnDefinitions>
    
      <Grid.RowDefinitions>
          <RowDefinition Height="50" />
          <RowDefinition Height="*" />
      </Grid.RowDefinitions>

请注意,星号 (“*”) 用于表示可用的剩余空间。这将导致列的宽度自动调整到 Grid 的宽度。现在,运行应用程序 (F5)。由于这是第一次运行应用程序,当出现以下窗口时,您应该会被提示启用调试

保留默认选择,然后单击“确定”按钮。

应用程序运行并加载网页后,您将能够看到网页如何分为两个独立的部分:顶部的标题和占据页面其余部分的数据部分。这是我的样子

关闭 Internet Explorer,然后返回 MainPage.xaml 编辑器。从 Grid 标签中删除 ShowGridLines=”True”

配置标题网格

在主网格的标题部分(第 0 行),我们将添加另一个网格,用于放置页面标题和用于检索和加载数据的按钮。

但在添加网格之前,添加一个漂亮的栗色边框,厚度为“1”。此边框将围绕网格。

<Border BorderBrush="Maroon" BorderThickness="1" >
</Border> 

Border 标签内添加网格,并将背景颜色设置为浅黄色。此外,向网格添加扩展属性,指示它位于主网格的标题部分(第 0 列;第 0 行)。

<Border BorderBrush="Maroon" BorderThickness="1" >
    <Grid Background="LightYellow" Grid.Column="0" Grid.Row="0" >
    </Grid>
</Border> 

为网格定义两列:第一列宽度为“*”,将存储标题。第二列宽度为“100”,将存储用于加载数据的按钮。

<Border BorderBrush="Maroon" BorderThickness="1" >
    <Grid Background="LightYellow" Grid.Column="0" Grid.Row="0" >
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="100" />
        </Grid.ColumnDefinitions>
    </Grid>
</Border> 

最后,添加一个 TextBlock 来显示页面标题。将 Text 设置为“AdventureWorks Contacts”。使用网格的扩展属性将 TextBlock 定位在第 0 列,第 0 行。

然后,添加一个 Button 用于显示数据。将其 Name 设置为 btnLoadContent 设置为“Load”,然后使用网格的扩展属性将 Button 定位在第 1 列,第 0 行。将 Click 属性设置为“btnLoad_Click”。

<Border BorderBrush="Maroon" BorderThickness="1" >
    <Grid Background="LightYellow" Grid.Column="0" Grid.Row="0" >
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="100" />
        </Grid.ColumnDefinitions>

        <TextBlock Padding="10,0,0,0" 
           VerticalAlignment="Center"  
           Text="AdventureWorks Contacts" 
           FontSize="28" 
           Foreground="Maroon"   
           Grid.Row="0" Grid.Column="0" />

        <Button x:Name="btnLoad" Content="Load" 
                VerticalAlignment="Center" 
                Margin="10" 
                Grid.Row="0" Grid.Column="1" 
                Click="btnLoad_Click"/>
    </Grid>
</Border> 

至此,标题部分就完成了!

在继续之前,找到 ButtonClick 属性,右键单击“btnLoad_Click”,然后选择“导航到事件处理程序”以创建相应的子例程。创建子例程后,返回 XAML 编辑器。

配置 DataGrid

接下来要做的就是向界面添加一个 Silverlight DataGrid。为此,请显示工具箱,找到 DataGrid 控件,然后将其拖到 XAML 编辑器上,并将其放在 </Border> 标签的正下方。

Name 设置为“dataGrid1”;将 AutoGenerateColumns 设置为“False”,因为我们将手动添加列;将 Visibility 设置为“Collapsed”,因为我们希望在页面加载时隐藏网格;然后使用主网格的扩展属性将 DataGrid 定位在第 0 列,第 1 行(这是主网格的底部)。

<data:DataGrid x:Name="dataGrid1"  
                AutoGenerateColumns="False" 
                Visibility="Collapsed"
                Grid.Row="1" Grid.Column="0" >
</data:DataGrid> 

我们要对 DataGrid 进行的最后一件事情是添加三个文本列:一个用于名字,一个用于姓氏,一个用于电子邮件。

特别注意下面的内容,每一列是如何通过设置 Binding 属性来绑定到 DataSource 的。此外,请注意 Binding 属性的值是如何使用 Binding 关键字和要绑定到的 DataSource 中的属性名称,以花括号 {} 括起来的字符串表达式。

<data:DataGrid x:Name="dataGrid1"  
                AutoGenerateColumns="False" 
                Visibility="Collapsed"
                Grid.Row="1" Grid.Column="0" >

    <data:DataGrid.Columns>

        <data:DataGridTextColumn 
            Binding="{Binding FirstName}" 
            Header="First Name" />

        <data:DataGridTextColumn 
            Binding="{Binding LastName}" 
            Header="Last Name" />

        <data:DataGridTextColumn 
            Binding="{Binding Email}" 
            Header="Email Address" />

    </data:DataGrid.Columns>

</data:DataGrid> 

此时,您可以保存项目(文件菜单 | 全部保存)。然后,运行应用程序 (F5)。最终结果应如下所示

关闭 Internet Explorer,完成后返回 XAML 编辑器。

添加 Visual Basic 代码

我们最后要做的是添加 Visual Basic 代码来将所有内容连接起来,并使其正常工作!所以,首先,右键单击 XAML 编辑器并选择“查看代码”以进入代码窗口。

在代码窗口的顶部,使用 WithEvents 关键字,向我们的 WCF 服务添加一个声明

'Create a new instance of our WCF Service
Private WithEvents mService As New ServiceReference1.Service1Client() 

然后,在代码窗口顶部的“类名”下拉列表中选择“mService”;接下来,在代码窗口顶部的“方法名”下拉列表中选择“GetContactsCompleted”。

从“方法名”下拉列表中选择“GetContactsCompleted”将创建 mService_GetContactsCompleted 事件处理程序。在此事件处理程序中,添加两行代码:一行将 DataGrid 加载到数据,另一行使网格可见

Private Sub mService_GetContactsCompleted( _
    ByVal sender As Object, _
    ByVal e As ServiceReference1 _
            .GetContactsCompletedEventArgs) _
    Handles mService.GetContactsCompleted

    dataGrid1.ItemsSource = e.Result

    dataGrid1.Visibility = Windows.Visibility.Visible

End Sub

GetContactsCompleted 事件处理程序在 WCF 服务从 SQL Server 检索数据并准备将数据传递给我们的 Silverlight 客户端后执行。

最后要做的是添加启动从我们的 WCF 服务获取联系人数据的异步过程的代码。将这一行代码添加到 btnLoad_Click 事件处理程序

Private Sub btnLoad_Click( _
        ByVal sender As System.Object, _
        ByVal e As System.Windows.RoutedEventArgs)
    mService.GetContactsAsync()
End Sub

所以,现在完整的代码窗口应该如下所示

Partial Public Class MainPage
    Inherits UserControl

    'Create a new instance of our WCF Service
    Private WithEvents mService As New ServiceReference1.Service1Client()

    Public Sub New()
        InitializeComponent()
    End Sub

    Private Sub btnLoad_Click( _
        ByVal sender As System.Object, _
        ByVal e As System.Windows.RoutedEventArgs)

        mService.GetContactsAsync()

    End Sub

    Private Sub mService_GetContactsCompleted( _
        ByVal sender As Object, _
        ByVal e As ServiceReference1 _
                .GetContactsCompletedEventArgs) _
        Handles mService.GetContactsCompleted

        dataGrid1.ItemsSource = e.Result

        dataGrid1.Visibility = Windows.Visibility.Visible

    End Sub

End Class 

就这么简单!

保存项目(文件菜单 | 全部保存)。然后运行应用程序 (F5)。当应用程序打开时,单击“Load”按钮以从 SQL Server AdventureWorks 数据库检索数据,并将其加载到 Silverlight DataGrid 中。如果一切正常,您应该会看到以下内容

摘要

本文演示了如何创建使用 LINQ to SQL 从 AdventureWorks 数据库的 Person.Contact 表检索数据的 WCF 服务,如何更新 web.config 文件的服务终结点配置以使 WCF 服务能够将结果返回给 Silverlight 客户端应用程序,以及如何从 Silverlight 客户端应用程序引用 WCF 服务,以及如何编写 Silverlight 客户端界面以在 Silverlight DataGrid 中显示检索到的数据。

© . All rights reserved.