Paul Cociuba shows us how to implement the Repository Pattern in ASP.NET 4.5.
In the last two videos of the series, we will focus on implementing the repository pattern for the sample application. This pattern is a way in which we can structure the code of the application to abstract away the data access code from the presentation layer through the usage of Interfaces. This will allow the layers of the application to become loosely coupled, achieving separation of concerns.
For your convenience, here’s a timeline through the above video.
1:08 – we start the implementation by looking at the ProductDetails.aspx page, which in its current state contains quite a few lines of code in the code behind, allowing for the selection, insertion and updating of products. Ideally, at the end of the implementation the code behind file should only contain code relating to presentation layer logic and nothing else.
2:00 – to abstract away the data-access code from the presentation layer, two new interfaces will be created in this part: the IToyCategoryRepository and the IProductRepository inside a new Repositories folder of the application. These interfaces will contain the method signatures that the future repository pattern classes will need to implement.
2:37 – inspection of the two interface definitions shows that IToyCategoryRepository defines a method signature for GetCategories. This method should return an IList<ToyCategory> to its caller. The IProductRepository defines a method signature for GetProducts that will return an IList<Product> to its callers.
3:30 – we now add the two classes that will implement the above interfaces, these are: ToyCategoryRepository and ProductRepository. Each of these classes will provide an implementation for GetCategories and GetProducts methods defined in the respective interface.
4:00 – to implement the interface definition in the class, we start by creating a new instance of the ProductContext object, and then copy the code of the GetCategories method from the code behind of the Categories.aspx page. This method will be modified to allow for input parameters which will give the caller (the DataBoundControl) the possibility to specify how the selection of data should be performed (in terms of sorting, number of rows to be returned, and row from which to start).
5:00 - The method implementation for GetCategories now starts by counting the total number of rows that could be returned by the query – so that the calling control can know how to paginate. The call to _db.Categories now also appends calls to extender methods that perform the sorting (Sort), define the number of records to be returned (Take) and the line number from which to start (Skip). The call to ToList() allows the method to return a list of ToyCategory objects, but also means that the SQL statement to retrieve the data is executed before the method returns and now when control reverts to the calling DataBound control.
5:58 – we make the same implementation changes to the ProductsRepository class when implementing the GetProducts method. The method will also allow for parameters to indicate the sorting, page size and starting line number of the records to be returned. Just like the GetCategories method, the call to _db.Produts includes the Sort, Take and Skip statements to allow the calling DataboundControl to drive the selection of data.
7:10 – in the next step we will add code to wire up the controls to the Interfaces of the repository automatically when the page is loaded. To achieve this, we define a new class (inside the ControlExtenders folder) that will define some extension methods for the DataboundControls. These methods will be called on the controls themselves even if the control does not implement them (see more about extensions methods here).
7:40 – We look more in depth at the code of the principal extension method defined in the class, the SetDataMethodsObject method. The code of the method will append an anonymous delegate to the list of delegates of the control’s CallingDataMethods event. The signature of the anonymous delegate is the following:
SomeDelegate_CallingDataMethods(object sender, CallingDataMethodsEventArgs e)
SomeDelegate_CallingDataMethods(object sender, CallingDataMethodsEventArgs e)
When the event is fired and the delegate is called, it sets the DataMethodObject property of the CallingDataMethodsEventArgs object e to point to parameter called dataMethodObject that was passed into the extension method.
8:21 – The other extension methods defined by the class are two overloads of the SetDefaultSort method. These allow the setting of the sort direction on a GridView control. The first overload takes in the expression by which to sort and the sorting direction, while the second only takes in a sort direction and sorts the data in ascending order.
9:03 – since we have all the necessary classes to implement the repository pattern, the focus now becomes to build a new instance of the category listings page (called CategoriesRep.aspx) that will make use of the pattern. To start, we transfer the markup of the Categories.aspx page to the CategoriesRep.aspx page since we will keep the same layout.
10:00 – going into the code behind of the new page, we start by bringing in the namespaces for the control extenders class (WebSample.Bll.Extensions) and the namespace for the repository pattern classes and interfaces (WebSample.Bll.Repository). Following this, we create a new instance of IToyCategoryRepository instead of creating an instance of the context object.
11:01 – In the Page_Load event of the new page, we call the extension methods. The first method to be called is SetDataMethodsObject to which we pass in the repository object as a parameter (note that Visual Studio is able to offer intelli-sence even for the extension methods – methods that are not declared by the control itself, but rather by the appended by the class we coded).
11:40 – Going back to the definition of the SetDataMethodsObject extension method, we see that the method takes the repository as a parameter, and, when the anonymous delegate is called, it will point the control to look for its data methods amongst (via the e.DataMethodObject) amongst the ones present in the repository implementation.
12:13 – We perform the same changes for the products listings page by creating a new ProductsRep.aspx page into which we copy the markup of the original Products.aspx page.
13:55 – Note that as opposed to the original implementation, we only bring in the name spaces that contain the classes that implement the extension methods and the implementation of the repository classes and interfaces. The objects that actually do the data access using Entity Framework and never exposed to the presentation layer, thus achieving the objective of a loosely coupled application.
14:27 – We then proceed to create a new instance of the IProductRepository which will replace the context object which was used in the older implementation of Products.aspx. The GridView is then hooked up to use the repository methods via the extension methods. If the page is not posting back, the SetDefaultSort extension method is called as well to sort the grid.
15:05 – We modify the existing routes to now point to the CategoriesRep.aspx and ProductsRep.aspx pages instead of the older versions.
15:50 - Running the sample now load the new implementation using the CategoriesRep.aspx page. The GridView inside the page is now sorted by the “Name” column in ascending order.
16:15 – Setting a breakpoint on the GetCategories method in the repository implementation shows that when clicking on the GridView control’s pagination to change pages to page 1, we can now inspect the parameters that the control sends down to the repository.
The next video in the series will expand on the Repository pattern implementation and will add the logic to perform insert, update and delete methods.
Original content from Paul Cociuba; posted by MSPFE editor Arvind Shyamsundar