Search code examples
silverlightwcf-ria-services

Access query parameters service side in RIA Services


If I have a service which directly extends DomainService is it possible to utilise the Take and Skip parameters in my service side query.

For example, here's my simple service...

[EnableClientAccess()]
public class StaffService : DomainService
{
    [Query]
    public IQueryable<StaffMember> GetStaffMembers()
    {
        var list = new List<StaffMember> 
        { 
            new StaffMember { Id=1, Name = "Bobby", JobDescription = "Driver" },
            new StaffMember { Id=2, Name = "Robert", JobDescription = "Driver's Mate" },
            new StaffMember { Id=3, Name = "Maxwell", JobDescription = "Diver" },
            new StaffMember { Id=4, Name = "Samuel", JobDescription = "Raver" }
        };

        return list.AsQueryable();
    }
}

and my simple query...

context.Load<StaffMember>(context.GetStaffMembersQuery().Skip(1).Take(2));

This works, only 2 of the 4 rows are returned but if this was accessing a database (using NHibernate for example) it would have had to return all the rows and then discard them.

I want to find the Skip and Take parameters so I can return the minimum data from the database.


Solution

  • it would have had to return all the rows and then discard them.

    no it does not as long as you are using IQueryable<T>. The IQueryable<T> interface is intended for implementation by query providers.

    From MSDN:

    These methods that extend IQueryable do not perform any querying directly. Instead, their functionality is to build an Expression object, which is an expression tree that represents the cumulative query.

    So your query, for instance

    public IQueryable<StaffMember> GetStaffMembers()
    {
        return dbContext.StaffMembers;
    }
    

    and on the client

    context.Load<StaffMember>(context.GetStaffMembersQuery().Skip(1).Take(2));
    

    will be translated by the TSQL generator in something like:

    SELECT TOP (2)
    [Extent1].[ID] AS [ID],
    [Extent1].[Name] AS [Name],
    FROM (
          SELECT [Extent1].[ID] AS [ID],
          [Extent1].[Name] AS [Name],
          row_number() OVER (ORDER BY [Extent1].[ID] ASC) AS [row_number]
          FROM [dbo].[StaffMember] AS [Extent1])  AS [Extent1]
    WHERE [Extent1].[row_number] > 1
    

    so only 2 items will be passed across the network.