Unifico has a few paging helpers to make service methods easily paged from a client. Essentially the framework makes consuming a page request object as simple as calling .ToList() on an IQueryable source. The object, the PageRequest, has two collections, Filters and Sorts with several constructors to make instantiation easy. The collections are rather straight forward, providing filtering and sorting ability on a paging source. The uniqueness comes from the ability to request multiple filters and sorts together, along with a paging request. This request is then execute on the IQueryable source, so if DLINQ is used, results in exactly two database hits. A COUNT statement is executed to find out how many pages there are, and a single select statement providing the paged results. This is all done without exposing LINQ or IQueryable to the service's client.
Making an existing source page-able is rather simple, compare the two implementations.
Without paging implemented:
44 public
List<App.Account.Models.Role> GetRoles()
45 {
46 return accountRepository.GetRoles().ToList();
47 }
With paging implemented:
43 public
PageResponse<App.Account.Models.Role> GetRolePage(PageRequest PageRequest)
44 {
45 return accountRepository.GetRoles().ToPageResponse(PageRequest);
46 }
Utilizing the paging is almost painfully easy.
Grabbing the first page at a size of ten:
120 PageResponse<Role> rolePage = accountService.GetRolePage(new
PageRequest(0, 10));
Or grabbing the first page sorting by the role's name (ascending):
120 PageResponse<Role> rolePage = accountService.GetRolePage(new
PageRequest(0, 10, "Name", "string", true));
Or fully defining the page request:
120 accountService.GetRolePage(new
PageRequest
121 {
122 Index = 2,
123 PageSize = 10,
124 Filters = new
ContractList<Filter>(
125 new[]{new
Filter { BinaryExpression=FilterBinaryExpression.Equal, Parameter="Name", TypeName="String",Value="Admin"},
126 new
Filter { BinaryExpression=FilterBinaryExpression.GreaterThan, Parameter="Level", TypeName="Int32", Value=1}}),
127 Sorts = new
ContractList<Sort>(
128 new[] { new
Sort { Ascending = true, TypeName = "Int32", Parameter = "Level" } })
129 });
130 /* Executes
131 SELECT [t1].[RoleID] AS [ID], [t1].[Name], [t1].[Level] AS [Level]
132 FROM (
133 SELECT ROW_NUMBER() OVER (ORDER BY [t0].[Level]) AS [ROW_NUMBER], [t0].[RoleID], [t0].[Name], [t0].[Level]
134 FROM [dbo].[Role] AS [t0]
135 WHERE ([t0].[Level] > 1) AND ([t0].[Name] = 'Admin')
136 ) AS [t1]
137 WHERE [t1].[ROW_NUMBER] BETWEEN 20 + 1 AND 20 + 10
138 ORDER BY [t1].[ROW_NUMBER]
139 */
I'm sure you have notice the TypeName properties and wondered why they are there. They enable the helper's methods to work with the expression tree before the query has been executed. Notice that the paging occurs in SQL against the table names and columns, not against the models. While the syntax is nowhere near that of LINQ, it seals of the service and keeps the paging responsibility within the service without requiring the service to handle specific paging requests. A similar method can be used to search multiple sources, and will be added shortly. Ohh, and it works across WCF.
The Unifico Framework