Data Access has been discontinued. Please refer to this page for more information.

Walkthrough: Adding Query Methods

This article is relevant to entity models that utilize the deprecated Visual Studio integration of Telerik Data Access. The current documentation of the Data Access framework is available here.

Methods that query a data source are sometimes called query methods. In WCF RIA Services, query methods must be defined in a way that the framework recognizes them as query methods. In addition, queries that always return a single entity are defined differently than queries that potentially return more than one entity.

To add a query method that accepts a parameter and returns a single entity:

  1. Open the solution that exposes data from the Customer table.
  2. In the server project, you will need to extend the domain service class that exposes data from the Customer table.
  3. Create a new class with the same name as the name of the domain service, e.g. SofiaCarRentalDomainService. The new partial class should be in the same namespace as the original, e.g OA.SL.RIA.Demo.Web.
  4. Add a query method that accepts an integer parameter and returns the Customer entity with the matching customerID.
  5. If a method that returns a single entity includes the QueryAttribute attribute, you must set the IsComposable property to false. Users cannot specify additional query operations from the client. If the query method matches the expected signature for a query, you do not have to apply the QueryAttribute attribute. The return value must be a single instance of an entity object.

    public partial class SofiaCarRentalDomainService
    {
       [Query( IsComposable = false )]
       public Customer GetCustomerById( int customerId )
       {
           return this.DataContext.Customers.SingleOrDefault<Customer>( c => c.CustomerID == customerId );
       }
    }
    
    Partial Public Class SofiaCarRentalDomainService
     <Query(IsComposable:=False)>
     Public Function GetCustomerById(ByVal customerId As Integer) As Customer
      Return Me.DataContext.Customers.SingleOrDefault(Function(c) c.CustomerID = customerId)
     End Function
    End Class
    

To add a query method that accepts a parameter and returns a collection of entities:

  1. Open the partial domain service class you created in the previous section.
  2. In the domain service, add a query method that accepts a string parameter and returns any customers whose full name starts with that letter. The method can return an IQueryable<> object because the user may want to provide additional query operations from the client.

    public partial class SofiaCarRentalDomainService
    {
       [Query( IsComposable = false )]
       public Customer GetCustomerById( int customerId )
       {
           return this.DataContext.Customers.SingleOrDefault<Customer>( c => c.CustomerID == customerId );
       }
       public IQueryable<Customer> GetCustomerByFullNameLetter( string startingFullNameLetter )
       {
           return this.DataContext.Customers.Where( c => c.FullName.StartsWith( startingFullNameLetter ) == true );
       }
    }
    
    Partial Public Class SofiaCarRentalDomainService
     <Query(IsComposable:=False)>
     Public Function GetCustomerById(ByVal customerId As Integer) As Customer
      Return Me.DataContext.Customers.SingleOrDefault(Function(c) c.CustomerID = customerId)
     End Function
     Public Function GetCustomerByFullNameLetter(ByVal startingFullNameLetter As String) As IQueryable(Of Customer)
      Return Me.DataContext.Customers.Where(Function(c) c.FullName.StartsWith(startingFullNameLetter) = True)
     End Function
    End Class
    

To display the results of those query methods in the client project:

  1. In the client project, open MainPage.xaml.
  2. Add two TextBox controls and two Button controls so that the user can filter the customer records by the ID or the first letter of the full name.
  3. The following XAML shows a complete layout along with the existing DataGrid.

    <UserControl xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
                x:Class="OA.SL.RIA.Demo.MainPage"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
       <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>
           <sdk:DataGrid Grid.Row="1"
                          Grid.Column="0"
                          Grid.ColumnSpan="2"
                          Name="CustomersDataGrid"/>
       </Grid>
    </UserControl>
    
  4. Open the code-behind page for MainPage.xaml.

  5. Add code to retrieve query results based on the user input.

    using System.ServiceModel.DomainServices.Client;
    using System.Windows.Controls;
    using OA.SL.RIA.Demo.Web;
    using System;
    namespace OA.SL.RIA.Demo
    {
       public partial class MainPage : UserControl
       {
           private SofiaCarRentalDomainContext domainContext = new SofiaCarRentalDomainContext();
           public MainPage()
           {
               InitializeComponent();
           }
           private void IDButton_Click( object sender, System.Windows.RoutedEventArgs e )
           {
               IDButton.IsEnabled = false;
               LetterButton.IsEnabled = false;
               LoadOperation<Customer> loadOp = this.domainContext.Load( this.domainContext
                   .GetCustomerByIdQuery( Convert.ToInt32( IDValue.Text ) ),
                        CustomerLoadedCallback, null );
               CustomersDataGrid.ItemsSource = loadOp.Entities;
           }
           private void LetterButton_Click( object sender, System.Windows.RoutedEventArgs e )
           {
               IDButton.IsEnabled = false;
               LetterButton.IsEnabled = false;
               LoadOperation<Customer> loadOp = this.domainContext.Load( this.domainContext
                   .GetCustomerByFullNameLetterQuery( LetterValue.Text ), 
                        CustomerLoadedCallback, null );
               CustomersDataGrid.ItemsSource = loadOp.Entities;
           }
           private void CustomerLoadedCallback( LoadOperation<Customer> loadOperation )
           {
               IDButton.IsEnabled = true;
               LetterButton.IsEnabled = true;
           }
       }
    }
    
    Imports System.ServiceModel.DomainServices.Client
    Imports OA.SL.RIA.Demo.Web
    Imports OA.SL.RIA.Demo.Web.OA.SL.RIA.Demo.Web
    Partial Public Class MainPage
        Inherits UserControl
        Private domainContext As New SofiaCarRentalDomainContext()
        Public Sub New()
            InitializeComponent()
        End Sub
        Private Sub IDButton_Click(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs)
            IDButton.IsEnabled = False
            LetterButton.IsEnabled = False
            Dim loadOp As LoadOperation(Of Customer) = Me.domainContext.Load(Me.domainContext _
                .GetCustomerByIdQuery(Convert.ToInt32(IDValue.Text)), _ 
                    AddressOf CustomerLoadedCallback, Nothing)
            CustomersDataGrid.ItemsSource = loadOp.Entities
        End Sub
        Private Sub LetterButton_Click(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs)
            IDButton.IsEnabled = False
            LetterButton.IsEnabled = False
            Dim loadOp As LoadOperation(Of Customer) = Me.domainContext.Load(Me.domainContext_
                .GetCustomerByFullNameLetterQuery(LetterValue.Text), 
                    AddressOf CustomerLoadedCallback, Nothing)
            CustomersDataGrid.ItemsSource = loadOp.Entities
        End Sub
        Private Sub CustomerLoadedCallback(ByVal loadOperation_Renamed As LoadOperation(Of Customer))
            IDButton.IsEnabled = True
            LetterButton.IsEnabled = True
        End Sub
    End Class
    
  6. Run the application. The following illustration shows a list of customers filtered by their id.