You are on page 1of 10



Learning MVC Part 6: Generic Repository Pattern in MVC3
Application with Entity Framework
Download Complete Source Code

Creating a Generic Repository pattern in an MVC3 application with Entity Framework is the last topic that we are
about to cover in our journey of learning MVC.
The article will focus on Unit of Work Pattern and Repository Pattern, and shows how to perform CRUD operations
in an MVC application when there could be a possibility of creating more than one repository class. To overcome
this possibility and overhead, we make a Generic Repository class for all other repositories and implement a Unit
of Work pattern to provide abstraction.

Our roadmap towards Learning MVC
Just to remind our full roadmap towards learning MVC,

1. Part1: Introduction to MVCarchitecture and Separation of Concerns.
2. Part 2: Creating MVC Application fromscratch and connecting it with database using LINQ to SQL.
3. Part 3: Connecting the MVC Application with the help of EntityFramework DB-First approach.
4. Part 4: Connecting the MVC Application with the help of EntityFramework Code-First approach.
5. Part 5: Implementing Repository Pattern in MVC Application with EntityFramework.
6. Part 6: Implementing a generic Repository Pattern and Unit Of Work pattern in MVC Application
with EntityFramework.

There are few pre-requisites before we start with the article,
1. We have running sample application that we created in fifth part of the article series.
2. We have Entity Framework 4.1 package or DLL on our local file system.
3. We understand how MVC application is created (follow second part of the series).

Why Generic Repository

which is impractical if you have a business transaction that spans multiple requests. Are we going to create these classes? Not good. The value of using a Unit of Work pattern is to free the rest of our code from these concerns so that you can otherwise concentrate on business logic. The Unit of Work pattern isn't necessarily something that you will explicitly build yourself. Moreover we save a lot of time that could be wasted creating those classes. The . Inside a single usage of a Unit of Work object. or deleted. it's important to keep track of what you've changed. "When you're pulling data in and out of a database. To order the database inserts. To prevent duplicate updates. you may want to write your own application-specific Unit of Work interface or class that wraps the inner Unit of Work from your persistence tool.We have already discussed what Repository Pattern is and why do we need Repository Pattern in our last article. You may do this for a number of reasons. newly created. and the ObjectContext class in the Entity Framework are all examples of a Unit of Work. To manage transactions. So to overcome this situation we’ll create a Generic Repository class that will be called by a property to create a new repository thus we do not result in lot of classes and also escape redundant code too. The Unit of Work will also have methods to commit or roll back all of the changes as well. but this can lead to lots of very small database calls. it results in a lot of redundant code. Unit of Work Pattern According to Martin Fowler Unit of Work Pattern “Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems. but think of the scenario where we need 10 such repositories. the DataContextclass in LINQ to SQL. We created a User Repository for performing CRUD operations. Similarly you have to insert new objects you create and remove any objects you delete. tracing." From MSDN. The important responsibilities of Unit of Work are. which ends up being very slow. You can change the database with each change to your object model. and updates. Why use Unit of Work? Again Martin Fowler statements. Furthermore it requires you to have a transaction open for the whole interaction. You might want to add application-specific logging. Perhaps you want to encapsulate the specifics of your persistence tooling from the rest of the application. The ITransaction interface in NHibernate. but the Unit of Work class will only issue a single UPDATE command to the database. deletes. different parts of the code may mark the same Invoice object as changed. You might want this extra encapsulation to make it easier to swap out persistence technologies later." The Unit of Work class can have methods to mark entities as modified. Many of the built-in Unit of Work implementations from common persistence tools are difficult to deal with in automated unit testing scenarios. or error handling to transaction management. that data won't be written back into the database. Or you might want to promote testability in your system. but the pattern shows up in almost every persistence tool. Other times. otherwise. For that matter. the venerable DataSet can be used as a Unit of Work.

and simpler to unit test(From MSDN). A Unit of Work keeps track and takes responsibility of everything you do during a business transaction that can affect the database.cs class is as follows: . Creating a Generic Repository Cut the Redundancy… Step 1: Open up our existing MVC3 application created in Part5 in Visual Studio. Traditionally. it figures out everything that needs to be done to alter the database as a result of your work. I prefer using the Unit of Work pattern to allow unrelated classes and services to take part in a logical transaction because I think it makes the code more explicit." You see I don’t have to concentrate much on theory.situation is even worse if you need to keep track of the objects you've read so you can avoid inconsistent reads.cs to that folder. Step2: Right click Learning MVC project folder and create a folder named GenericRepository and add a class namedGenericRepository. Using the Unit of Work One of the best ways to use the Unit of Work pattern is to allow disparate classes and services to take part in a single logical transaction. The code of the GenericRepository. easier to understand. we already have great definitions existing. Personally. The key point here is that you want the disparate classes and services to remain ignorant of each other while being able to enlist in a single transaction. all we needed is to stack them in a correct format. When you're done. you've been able to do this by using transaction coordinators like MTS/COM+ or the newer System.Transactions namespace.

namespace LearningMVC.Entry(entityToDelete).GenericRepository { public class GenericRepository<TEntity> where TEntity : class { internal MVCEntities context.ToList(). System.Set<TEntity>().State = EntityState. internal DbSet<TEntity> dbSet. } public virtual void Delete(TEntity entityToDelete) { if (context. System. System.using using using using using using System. Delete(entityToDelete). System. } public virtual void Insert(TEntity entity) { dbSet.Data.Linq. System.Find(id).Entry(entityToUpdate).Detached) { dbSet. } public virtual TEntity GetByID(object id) { return dbSet.Attach(entityToUpdate).Expressions. } dbSet.Generic. } } } .Collections.Remove(entityToDelete). } public virtual void Delete(object id) { TEntity entityToDelete = dbSet.State == EntityState.Data.Modified. } public virtual void Update(TEntity entityToUpdate) { dbSet.Linq.Attach(entityToDelete). return query. public GenericRepository(MVCEntities context) { this.Entity. } public virtual IEnumerable<TEntity> Get() { IQueryable<TEntity> query = dbSet. context. this.Add(entity).context = context.dbSet = context.Find(id).

and add a class UnitOfWork.userRepository = new GenericRepository<User> (context). return userRepository. private GenericRepository<User> userRepository. note that earlier it was used to be passed in Repository class from .UnitOfWork { public class UnitOfWork : IDisposable { private MVCEntities context = new MVCEntities(). TEntity is any model/domain/entity class.GenericRepository. protected virtual void Dispose(bool disposing) { if (!this. } public void Dispose() { Dispose(true). Step 3: Implementing UnitOfWork: Create a folder named UnitOfWork under LearningMVC project.SaveChanges().We can see.Dispose().disposed = true. using LearningMVC.cs to that folder. when instantiating this class we can pass any model on which the class will work as a repository and serve the purpose. } } } We see the class implements IDisposable interface for objects of this class to be disposed. } private bool disposed = false.SuppressFinalize(this). we have created the generic methods and the class as well is generic. The code of the class is as follows: using System. We create object of DBContext in this class. } } public void Save() { context.disposed) { if (disposing) { context. GC. public GenericRepository<User> UserRepository { get { if (this. MVCEntities is our DBContext as discussed in earlier parts. } } this. namespace LearningMVC.userRepository == null) this.

mere 6-7 lines of code..a controller.So we can choose any of the repositories created and perform CRUD operations on them. our Index action: . Now this unitOfWork instance of UnitOfWork class holds all th repository properties.userRepository = new GenericRepository<User> (context). (Taken from Google) You see it was as simple as that.if we press “." After it. confused???? Yes it'sDBOperations. Step 4: In MyController. return userRepository.UnitOfWork(). and no need to create separate classes. We see in the code itself that.g. } } I. it will show the repositories. you can create as many repositories you want by just creating simple properties. let's do it. E.UnitOfWork unitOfWork = new UnitOfWork. public GenericRepository<User> UserRepository { get { if (this.userRepository == null) this. And now you can complete the rest of the story by yourself. of type GenericRepository serving User entity to TEntity template.e. declare a variable unitOfWork as: private UnitOfWork. Guess what? Our UserRepository is created. Now it's time to create our User Repository. simply a variable named userRepositoryis declared as private GenericRepository userRepository. Then a property is created for the same userRepository variable in a very simplified manner.

Address. } } ViewBag. Address = user. no need to write that constructor.Any()) { foreach (var user in userList) { users. var users = new List<LearningMVC. } return View(users).LastName. } Now.UserList() { UserId = user. LastName = user.FirstName.public ActionResult Index() { var userList = from user in unitOfWork. } Here.UserRepository.UserList>(). Details . in fact you can remove the UserRepository class and Interface we created in part 5 of Learning MVC. if(TempData. Earlier we used to have MyController constructor like: public MyController() { this.UserRepository > Accessing UserRepository. FirstName = user.Designation.Any()) { var tempData = TempData["TempData Name"].EMail. Company = user. ViewData["FirstName"] = "My First Name". Designation = user.Models. unitOfWork. if (userList. PhoneNo = user.Models.UserId.userRepository = new UserRepository(new MVCEntities()).Get() -> Accessing Generic Get() method to get all users.Get() select user.FirstName = "My First Name".Company. EMail = user.PhoneNo }). I hope you can write the Actions for rest of the CRUD operations as well.Add(new LearningMVC. unitOfWork.UserRepository.

Address. user. user.UserList userDetails) { try { var user = new User().UserId.EMail = userDetails. user. user.public ActionResult Details(int id) { var userDetails = unitOfWork. } } Edit: .UserId = userDetails.Designation.Save().Company = userDetails.Models. user.Company.FirstName.PhoneNo = userDetails. } Create: [HttpPost] public ActionResult Create(LearningMVC.LastName.UserList(). } catch { return View().EMail. user.Company.UserId. return RedirectToAction("Index"). user. user.Designation = userDetails.Company = userDetails.UserId = userDetails.Address = userDetails. if (userDetails != null) { user.EMail.Designation.LastName = userDetails.LastName = userDetails.Models.FirstName = userDetails. user. } return View(user).PhoneNo. if (userDetails != null) { user.FirstName.Address = userDetails.Insert(user).PhoneNo = userDetails.UserRepository. user.Address. user. var user = new LearningMVC. user. } unitOfWork. user.LastName. user.FirstName = userDetails.UserRepository.EMail = userDetails.PhoneNo. unitOfWork.GetByID(id).Designation = userDetails.

GetByID(id).PhoneNo = userDetails.UserId = userDetails.Company. user.PhoneNo. user.EMail. user.UserId. user. user. var user = new LearningMVC.Designation.LastName = userDetails.PhoneNo. user. } return View(user). user.FirstName = userDetails.LastName.Address = userDetails. } [HttpPost] public ActionResult Edit(int id. try { var user = unitOfWork.Designation.UserRepository. user. User userDetails) { TempData["TempData Name"] = "Akhil".PhoneNo = userDetails. return RedirectToAction("Index"). unitOfWork. user.UserList().Company.FirstName.LastName.EMail.public ActionResult Edit(int id) { var userDetails = unitOfWork.Company = userDetails. user.LastName = userDetails.Company = userDetails.GetByID(id).Models.FirstName.Address. if (userDetails != null) { user. unitOfWork. user.Save().FirstName = userDetails. user.Address.UserRepository.UserRepository. } Delete: .EMail = userDetails.Designation = userDetails. user. user.Designation = userDetails.Update(user).Address = userDetails.EMail = userDetails.

visit my blog A Practical Approach . } return View(user).Designation. Happy coding :-). var userDetails = unitOfWork. user.Company = userDetails.PhoneNo.UserRepository. if (userDetails != null) { user.UserRepository. let me know if you feel to discuss any topic in particular or we can also start any other series as well. user.GetByID(id).PhoneNo = userDetails.GetByID(id). We have also learnt UnitOfWork pattern in detail.LastName = userDetails.Company. user.Save(). if (user != null) { unitOfWork.Models. } catch { return View().Models. } } Note: Images are taken from Google images.FirstName. user.Designation = userDetails.UserList().public ActionResult Delete(int id) { var user = new LearningMVC. user. Now you are qualified and confident enough to apply these concepts in your enterprise applications. LearningMVC. . Conclusion We now know how to make generic repositories too.UserRepository. For more informative articles. } return RedirectToAction("Index").Delete(id).Address = userDetails.EMail = userDetails.EMail. unitOfWork. user.UserList userDetails) { try { var user = unitOfWork. } [HttpPost] public ActionResult Delete(int id.LastName. and perform CRUD operations using it.FirstName = userDetails. This was the last part of this MVC series.Address.