演练:添加查询方法
本演练描述如何在 WCF RIA Services 中添加和自定义用于查询数据源的方法。必须使用框架认定为指定查询方法的签名来定义此类方法(称为查询方法)。查询方法通过应用 QueryAttribute 来满足此要求。预期的一组查询签名分为两大类:始终返回单一类型的 Entity 的那些查询,以及可能在 IEnumerable 或 IQueryable 中返回类型为 T 的多个 Entity 的那些查询。有关允许的查询方法签名的更多信息,请参见域服务。
当您创建一个新的域服务类并在**“添加新的域服务类”**对话框中指定其实体后,RIA Services 框架会自动在此类中为该服务公开的每个实体创建一个简单的查询方法。此查询方法只检索该实体的所有记录。本演练介绍如何添加新的查询方法以执行更复杂的情形,如依据参数值进行筛选。本演练演示如何添加返回单个实体的查询,同时还演示如何添加返回实体集合的查询。
必备条件
本演练和 RIA Services 文档中提供的其他演练除了要求正确安装和配置 WCF RIA Services 和 WCF RIA Services 工具包外,还要求正确安装和配置几个必备程序,如 Visual Studio 2010 以及 Silverlight Developer Runtime 和 SDK。它们还要求安装和配置具有高级服务的 SQL Server 2008 R2 Express 以及安装 AdventureWorks OLTP 和 LT 数据库。
WCF RIA Services 的必备条件节点中的主题提供有关如何满足这些前提条件的详细说明。在执行本演练前请按照那里提供的说明操作,以确保在执行本 RIA Services 演练时遇到的问题最少。
本演练假定您已完成演练:创建 RIA Services 解决方案中介绍的过程,并在该演练中创建了可在此处所述的过程中修改的解决方案。
添加接受参数并返回单个实体的查询方法
打开在演练:创建 RIA Services 解决方案主题(公开 Customer 表中的数据)中构建的解决方案。
在服务器项目中,打开公开 Customer 表中的数据的
CustomerDomainService
域服务类。添加接受一个整数参数并返回具有匹配客户 ID 的
Customer
实体的查询方法。如果返回单个实体的方法包括 QueryAttribute 特性,则必须将 IsComposable 属性设置为 false。用户不能从客户端指定其他查询操作。如果该查询方法与某个查询的预期签名匹配,则不必应用 QueryAttribute 特性。返回值必须是单个实体对象实例。
<Query(IsComposable:=False)> Public Function GetCustomersByID(ByVal customerID As Integer) As Customer Return Me.ObjectContext.Customers.SingleOrDefault(Function(c) c.CustomerID = customerID) End Function
[Query(IsComposable=false)] public Customer GetCustomersByID(int customerID) { return this.ObjectContext.Customers.SingleOrDefault(c => c.CustomerID == customerID); }
添加接受参数并返回实体集合的查询方法
打开公开 Customer 表中的数据的域服务类。
在
CustomerDomainService
域服务类中,添加接受一个字符串参数并返回姓氏以该字母开头的所有客户的查询方法。该方法可返回一个 IQueryable对象,因为用户可能希望从客户端提供其他查询操作。
Public Function GetCustomersByLastNameLetter(ByVal startingLastNameLetter As String) As IQueryable(Of Customer) Return Me.ObjectContext.Customers.Where(Function(c) c.LastName.StartsWith(startingLastNameLetter) = True) End Function
public IQueryable<Customer> GetCustomersByLastNameLetter(string startingLastNameLetter) { return this.ObjectContext.Customers.Where(c => c.LastName.StartsWith(startingLastNameLetter) == true); }
在客户端项目中显示这些查询方法的结果。
在客户端项目中,打开 MainPage.xaml。
添加两个 TextBox 控件和两个 Button 控件,以便用户可以依据 ID 或姓氏的第一个字母来筛选客户记录。
下面的 XAML 演示了连同现有的 DataGrid 在内的完整布局。
<UserControl xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" x:Class="RIAServicesExample.MainPage" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="https://schemas.microsoft.com/expression/blend/2008" xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <Grid x:Name="LayoutRoot" Background="White"> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="25"></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="0"> <TextBlock Text="search by id: " ></TextBlock> <TextBox Name="IDValue" Width="50" ></TextBox> <Button Name="IDButton" Click="IDButton_Click" Content="Submit"></Button> </StackPanel> <StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="1"> <TextBlock Text="search by name: "></TextBlock> <TextBox Name="LetterValue" Width="30"></TextBox> <Button Name="LetterButton" Click="LetterButton_Click" Content="Submit"></Button> </StackPanel> <data:DataGrid Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Name="CustomerGrid"></data:DataGrid> </Grid> </UserControl>
打开 MainPage.xaml 的代码隐藏文件(MainPage.xaml.cs 或 MainPage.xaml.vb)。
添加代码以便基于用户输入检索查询结果。
Imports RIAServicesExample.Web Imports System.ServiceModel.DomainServices.Client Partial Public Class MainPage Inherits UserControl Dim _customerContext As New CustomerDomainContext Public Sub New() InitializeComponent() End Sub Private Sub LetterButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) IDButton.IsEnabled = False LetterButton.IsEnabled = False Dim loadOp = Me._customerContext.Load(Me._customerContext.GetCustomersByLastNameLetterQuery(LetterValue.Text), AddressOf CustomerLoadedCallback, Nothing) CustomerGrid.ItemsSource = loadOp.Entities End Sub Private Sub IDButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) IDButton.IsEnabled = False LetterButton.IsEnabled = False Dim loadOp = Me._customerContext.Load(Me._customerContext.GetCustomersByIDQuery(IDValue.Text), AddressOf CustomerLoadedCallback, Nothing) CustomerGrid.ItemsSource = loadOp.Entities End Sub Public Sub CustomerLoadedCallback(ByVal loadOperation As LoadOperation(Of Customer)) IDButton.IsEnabled = True LetterButton.IsEnabled = True End Sub End Class
using System; using System.Windows; using System.Windows.Controls; using RIAServicesExample.Web; using System.ServiceModel.DomainServices.Client; namespace RIAServicesExample { public partial class MainPage : UserControl { private CustomerDomainContext _customerContext = new CustomerDomainContext(); public MainPage() { InitializeComponent(); } private void LetterButton_Click(object sender, RoutedEventArgs e) { IDButton.IsEnabled = false; LetterButton.IsEnabled = false; LoadOperation<Customer> loadOp = this._customerContext.Load(this._customerContext.GetCustomersByLastNameLetterQuery(LetterValue.Text), CustomerLoadedCallback, null); CustomerGrid.ItemsSource = loadOp.Entities; } private void IDButton_Click(object sender, RoutedEventArgs e) { IDButton.IsEnabled = false; LetterButton.IsEnabled = false; LoadOperation<Customer> loadOp = this._customerContext.Load(this._customerContext.GetCustomersByIDQuery(int.Parse(IDValue.Text)), CustomerLoadedCallback, null); CustomerGrid.ItemsSource = loadOp.Entities; } void CustomerLoadedCallback(LoadOperation<Customer> loadOperation) { IDButton.IsEnabled = true; LetterButton.IsEnabled = true; } } }
运行 (F5) 该应用程序。
下图显示了依据在运行该应用程序后出现的姓氏进行筛选的客户的列表。