Implementation of Repository Design Pattern with ASP.NET MVC 2

Repository pattern plays a significant role when it comes to create separation of concern between data access and business logic layer.

There are several benefits of using this design pattern:

  1. It increases unit testability in your application.
  2. Improve maintainability of your data access code
  3. Clear separation of concern between data access layer and business logic layer
  4. Provide flexible pluggable architecture for any data access logic and remove any internal plumbing details from business logic
  5. And many others

Today, we will implement this design pattern in ASP.NET MVC 2 application.

To get started choose new project and ASP.NET MVC 2 Empty Web Application with name "RepositoryDesignPattern"

Next, inside your Models folder create two new folders with name "Abstract" and "Concrete"

We will create new class inside Models folder with name Products.cs:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

 

namespace RepositoryDesignPattern.Models

{

public class Product

{

public int ProductId { get; set; }

public string ProductName { get; set; }

public double UnitPrice { get; set; }

}

}

 

Now, we will create Interface inside Abstract folder with name "IProductsRepository.cs".

In this interface we will define what all methods that we wish to implement inside our concrete folder.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace RepositoryDesignPattern.Models.Abstract

{

public interface IProductsRepository

{

List<Product> ListOfProducts();

}

}

 

This interface will help keeping our implementation separate and all the internal plumbing details of data access will be separate from actual logic.

Once we have our interface created we will give it concrete implementation.

To see how easy it is to change source of data, we will create two implementations, one for test (in memory collection) and second for database (ADO.NET).

Let's create a new class in our concrete folder with name "TestProductsRepository.cs" and implement IProductsRepository interface:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using RepositoryDesignPattern.Models.Abstract;

 

namespace RepositoryDesignPattern.Models.Concrete

{

public class TestProductsRepository : IProductsRepository

{

List<Product> _productRepository=new List<Product> {

new Product{ProductId=1,ProductName="Play Station 3", UnitPrice=200},

new Product{ProductId=1,ProductName="Wii", UnitPrice=100},

new Product{ProductId=1,ProductName="XBox", UnitPrice=250},

new Product{ProductId=1,ProductName="PSP", UnitPrice=150}

};

 

public List<Product> ListOfProducts()

{

return _productRepository;

}

}

}

 

Let's create another class with name "DBProductsRepository.cs". Here we will connect to the database using ADO.NET

using System.Linq;

using System.Web;

using System.Web.Configuration;

using RepositoryDesignPattern.Models.Abstract;

using System.Data.SqlClient;

 

namespace RepositoryDesignPattern.Models.Concrete

{

public class DBProductsRepository : IProductsRepository

{

private string connString=WebConfigurationManager.ConnectionStrings["SqlConnectionString"].ConnectionString;

 

 

public List<Product> ListOfProducts()

{

return GetDBProducts();

}

 

private List<Product> GetDBProducts()

{

List<Product> prodCollection = new List<Product>();

using (SqlConnection conn=new SqlConnection(connString))

{

using (SqlCommand cmd=new SqlCommand())

{

cmd.Connection = conn;

cmd.CommandText = "GetProducts";

cmd.CommandType = System.Data.CommandType.StoredProcedure;

conn.Open();

SqlDataReader reader = cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);

while (reader.Read())

{

Product prod = new Product();

prod.ProductId = Convert.ToInt32(reader[0]);

prod.ProductName = Convert.ToString(reader[1]);

prod.UnitPrice = Convert.ToDouble(reader[2]);

prodCollection.Add(prod);

}

reader = null;

}

}

return prodCollection;

}

}

}

 

Something to notice here: since both classes return collection of product, for our application it's not going to matter where the data is coming from and how we are getting that data until it gets the data.

Now inside our controller folder, we will create a new controller by right clicking on the controller folder and creating a new controller with name "ProductController"

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.Mvc;

using RepositoryDesignPattern.Models.Abstract;

using RepositoryDesignPattern.Models.Concrete;

 

namespace RepositoryDesignPattern.Controllers

{

public class ProductController : Controller

{

IProductsRepository productRepository;

 

public ProductController()

{

productRepository = new DBProductsRepository();

}

 

public ActionResult Index()

{

return View(productRepository.ListOfProducts());

}

}

}

 

 

Code above is creating an instance of our IProductsRepository interface, and assigning it with one of the concrete implementation of our interface, inside ProductController's default constructor.

Once initialized, we will return a strongly typed view passing our list of products as Model. So let's create a view.

Right click anywhere inside Index action method of ProductController and select Add View with following details selected:

Inside the view paste following code:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<IEnumerable<RepositoryDesignPattern.Models.Product>>" %>

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

 

<html xmlns="http://www.w3.org/1999/xhtml" >

<head runat="server">

<title>Index</title>

<link href="<%: Url.Content("~/Content/Site.css") %>" rel="stylesheet" type="text/css" />

 

</head>

 

<body>

<table>

<tr>

 

<th>

ProductId

</th>

<th>

ProductName

</th>

<th>

UnitPrice

</th>

</tr>

 

<% foreach (var item in Model) { %>

 

<tr>

<td>

<%: item.ProductId %>

</td>

<td>

<%: item.ProductName %>

</td>

<td class="amount">

<%: String.Format("{0:C}", item.UnitPrice) %>

</td>

</tr>

 

<% } %>

 

</table>

 

 

</body>

</html>

 

 

All this code is doing is iterating through the model and listing all details inside a table.

One last thing before we run our project:

Open and update Global.asax file's route values as follows:

routes.MapRoute(

"Default", // Route name

"{controller}/{action}/{id}", // URL with parameters

new { controller = "Product", action = "Index", id = UrlParameter.Optional } // Parameter defaults

);

To make our data table look pretty, add following css inside Site.css located in Content folder:

table

{

border-collapse:collapse;

}

 

table, td

{

border:1px solid #334455;

padding:0 2px 0 2px;

}

 

th

{

background-color:#5656aa;

color:White;

padding:0 5px 0 5px;

}

 

.amount

{

text-align:right;

}

 

 

Let's run the project:

 

Now just to show you how it is to change the data source. Go back to your project and change DBProductsRepository to TestProjectsRepository and run the project again:

 

 

Tags: , , , , ,

ASP.NET | MVC | Design Patterns