In my approach I wish to implement all my business logic and services by using Service Factory design pattern for WCF. Because I going to focus only at the pagination mechanism there is no need to add additional classes for accessing an database that is why I going to use mocking to create some data except.
At the beginning take a look at solution high level architecture (picture 1.). The solution contains two separated solution folder. Tests folders contains only one console application project for web service testing purposes. Folder WCF contains following projects:
- Common: dll with implementation of public interfaces and classes shared across whole solution.
- Contracts: dll with definitions for classes uses as parameters for services methods. According best practices all service methods take 0 or only one parameter(which always derive from BaseRequest class) and returns type of response (which always derive from BaseResponse class).
- DataTransferObjects: dll with types uses in communication in requests and responses. These types implements interfaces from namespaces Common.DTO and database entities also should implements its.
- Namespaces: dll with constans namespaces for services, services contracts, service interfaces and so on.
- ServiceImplementation: dll, core library with implementation of business logic for WCF services where classes implements service contracts.
- ServiceInterfaces: dll, services contracts.
- Services: WCF application, stores .svc files and configuration file (Web.config)
|Picture 1. solution high level architecture.|
To enable pagination for list some additional implementation had to be introduced (picture 2.). The most important class for that is generic ListRequest<T> which implements a generic interface IRaginationRequest<T>. Those interface has only two int null-able properties which determine number of page to display and number of result per page - by default pagination return first page with maximum 20 results. Because we I use here genetic types in GetUserRequest declaration I simply can declare type of T as User type which is my DTO object.
|Picture 2. Structure of a pagination request.|
|Picture 3. Structure for a pagination response.|
Now its time to implement service logic for returning paginated list of users. As I mentioned before in this post, I using mocking except of database that is why I create 100 users in for loop with some test properties. After filling the list it`s time for apply pagination mechanism on it. For pagination I`ve created extension generic method called AsPagination which extend IEnumerable interface of T type and takes one generic parameter of type IPaginationRequest. This is quite obvious because in the request (which implements that interface) we pass all required data for pagination. Because pagination function returns value of generic type IPagination and there is no possibility to pass interface by WCF it need to be converted to class type and this explains GetUserResponse structure (Picture 3.).
To fully understand pagination mechanism you must be familiar with IQueryable interface and deferred execution on queries because both are used in the implementation. Pagination mechanism is optimized which means that you get only records which you really requested. For example, if you want to see 10 record on 5th page you need get from database only 10 records. You can achieve this by using Skip and Take LINQ functions and know page size and number.If know both value of these variables you can simply use following LINQ query:
|Picture 4. Pagination mechanism overview.|
At this stage there is no sorting and ordering in pagination list because it will be introduced in further post.
Full projects source code is free available here.
- Deferred query execution: http://msdn.microsoft.com/en-us/library/bb738633(v=vs.100).aspx
- WCF Service Factory: http://msdn.microsoft.com/en-us/magazine/cc163481.aspx