Click here to Skip to main content
15,879,535 members
Articles / Web Development / HTML

Learning MVC - Part 5 Repository Pattern in MVC3 Application with Entity Framework

Rate me:
Please Sign up or sign in to vote.
4.73/5 (71 votes)
17 Mar 2015CPOL7 min read 244.5K   12.5K   182   44
Repository pattern in MVC3 application with entity framework

Introduction

In our last four articles, we learnt almost everything about how to create an MVC application and how to communicate with database using the same application.

In the third part of learning MVC, we learnt communication between MVC application and database using EntityFramework, so I am referring to the same context. In this article, I’ll focus on how to implement a Repository Pattern in the same MVC application, therefore moving ahead a step towards architectural approach of developing an enterprise application.

Our Roadmap

Just to remind you of our full roadmap towards learning MVC:

Pre-requisites

There are a few pre-requisites before we start with the article:

  1. We have running sample application that we created in the third part of the article series.
  2. We have EntityFramework 4.1 package or DLL on our local file system.
  3. We understand how the MVC application is created.

Repository Pattern

Very few authors explain the concept and jump directly over the practical implementation of the pattern. So, first let us understand what is repository pattern? Why should we use it?

In simple terms, a repository basically works as a mediator between our business logic layer and our data access layer of the application. Sometimes, it would be troublesome to expose the data access mechanism directly to business logic layer, it may result in redundant code for accessing data for similar entities or it may result in a code that is hard to test or understand. To overcome these kinds of issues, and to write an Interface driven and test driven code to access data, we use Repository Pattern. The repository makes queries to the data source for the data, thereafter maps the data from the data source to a business entity/domain object, finally and persists the changes in the business entity to the data source. According to MSDN, a repository separates the business logic from the interactions with the underlying data source or Web service. The separation between the data and business tiers has three benefits:

  • It centralizes the data logic or Web service access logic.
  • It provides a substitution point for the unit tests.
  • It provides a flexible architecture that can be adapted as the overall design of the application evolves.

When we use Entity Framework, as we did in our last application created, we were calling the Entity Framework class object in the controller class for accessing the entity classes. Now we can say that that system was somewhat a tightly coupled system. To overcome this situation, as we discussed, we’ll implement Repository Pattern.

In Repository, we write our whole business logic of CRUD operations with the help of Entity Framework classes, that will not only result in meaningful test driven code but will also reduce our controller code of accessing data.

Creating Repository

Creating Repository is not as tough at it sounds to be, once you implement this by your own, you’ll love it.

Step 1: Open up our existing MVC3 application in Visual Studio, that we created in the third part to interact with database with the help of Entity Framework.

Step 2: Create a folder named Repository and add an Interface to that folder named IUserRepository, this interface we derive from IDisposable type of interface.

We’ll declare methods for CRUD operations on User entity class over here, you can choose the names of the method as per your choice, but those should be easy to understand and follow.

Like I used in the below code of my interface:

C#
using System;
using System.Collections.Generic;

namespace LearningMVC.Repository
{
    public interface IUserRepository:IDisposable
    {
        IEnumerable<User> GetUsers();
        User GetUserByID(int userId);
        void InsertUser(User user);
        void DeleteUser(int userId);
        void UpdateUser(User user);
        void Save();
    }
}

We can see each method name signifies particular CRUD operation on User entity.

User Entity is the same entity we generated in Model.tt class in Part3 of learning MVC, remember???????

Step 3: Extract a class from that interface and call it UserRepository. This UserRepository class will implement all the methods of that interface, but with the help of Entity Framework. Now here comes the use of our DBContext class MVCEntities, we already have this class in our existing solution, so we don’t have to touch this class, simply, write our business logic in the interface methods implemented in UserRepository class:

C#
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;

namespace LearningMVC.Repository
{
    public class UserRepository:IUserRepository
    {
        private MVCEntities context;

        public UserRepository(MVCEntities context)
        {
            this.context = context;
        }

        public IEnumerable<User> GetUsers()
        {
            return context.Users.ToList();
        }

        public User GetUserByID(int userId)
        {
            return context.Users.Find(userId);
        }

        public void InsertUser(User user)
        {
            context.Users.Add(user);
        }

        public void DeleteUser(int userId)
        {
            User user = context.Users.Find(userId);
            context.Users.Remove(user);
        }

        public void UpdateUser(User user)
        {
            context.Entry(user).State = EntityState.Modified;
        }

        public void Save()
        {
            context.SaveChanges();
        }

        private bool disposed = false;

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    context.Dispose();
                }
            }
            this.disposed = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }
}

And inside the solution:

Interface

Image 1

Class

Image 2

90% of the job is done now. Now the only thing left is to use this repository in our controller.

This is needless to explain how you’ll call repository inside the controller, as you now know how to treat our controller, but still let's do it for once.

Step 4: Go to the controller, declare the IUserRepository reference, and in the constructor initialize the object with UserRepository class, passing MVCEntities to the constructor as parameter we defined in UserRepository class:

C#
#region Private member variables...
private IUserRepository userRepository; 
#endregion

#region Public Constructor...
/// <summary>
/// Public Controller to initialize User Repository
/// </summary>
public MyController()
{
this.userRepository = new UserRepository(new MVCEntities());
} 
#endregion

In the solution, this will look like:

Image 3

Step 5: Now for all the actions of the controller in which we were using Entity Framework context directly, we replace the calling logic by the created userRepository object, and call methods defined in repository class.

Like, in Index controller, where we show the list of users, we do:

C#
var userList = from user in userRepository.GetUsers() select user;
            var users = new List<LearningMVC.Models.UserList>();
            if (userList.Any())
            {
                foreach (var user in userList)
                {
                    users.Add(new LearningMVC.Models.UserList() 
                    { UserId = user.UserId, Address = user.Address, 
                    Company = user.Company, FirstName = user.FirstName, 
                    LastName = user.LastName, Designation = user.Designation, 
                    EMail = user.EMail, PhoneNo = user.PhoneNo });
                }
            }

We can see the earlier code used remained the same, only a layer has been introduced between Entity Framework data access layer and business logic, and the controller now only uses that abstracted layer to communicate with database.

Image 4

Similarly for other Actions of the controller:

Details

Image 5

Create

Image 6

Edit

Image 7

Delete

Image 8

Step 6: Run the application, and we see the application running as it was earlier:

Image 9

Now that’s party time.

Conclusion

We now know how to make repositories too, and perform CRUD operations using it.

Now we can visualize how useful the pattern is and how it solved our issues of tight coupling and resulted in an appropriate architecture.

As per MSDN, Use the Repository pattern to achieve one or more of the following objectives:

  • You want to maximize the amount of code that can be tested with automation and to isolate the data layer to support unit testing.
  • You access the data source from many locations and want to apply centrally managed, consistent access rules and logic.
  • You want to implement and centralize a caching strategy for the data source.
  • You want to improve the code's maintainability and readability by separating business logic from data or service access logic.
  • You want to use business entities that are strongly typed so that you can identify problems at compile time instead of at run time.
  • You want to associate a behavior with the related data. For example, you want to calculate fields or enforce complex relationships or business rules between the data elements within an entity.
  • You want to apply a domain model to simplify complex business logic.

And I fully agree to it, but has our application made use of the pattern appropriately? What if there are 100s of Repositories that need to be created? What if we have 100s of entities? Do we create Repositories for all of them, resulting in a mess and code redundancy? The answer is a big NO. In my next and last article of the series, we’ll learn how to create a Generic Repository to serve the purpose of n number of Entities. The source code of this article and existing article, i.e., Part 3 along with database scripts has been attached. You can download and run the solution, and drop me a question in case you feel like it. I’ll be happy to answer.

Happy coding :) 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect https://codeteddy.com/
India India
Akhil Mittal is two times Microsoft MVP (Most Valuable Professional) firstly awarded in 2016 and continued in 2017 in Visual Studio and Technologies category, C# Corner MVP since 2013, Code Project MVP since 2014, a blogger, author and likes to write/read technical articles, blogs, and books. Akhil is a technical architect and loves to work on complex business problems and cutting-edge technologies. He has an experience of around 15 years in developing, designing, and architecting enterprises level applications primarily in Microsoft Technologies. He has diverse experience in working on cutting-edge technologies that include Microsoft Stack, AI, Machine Learning, and Cloud computing. Akhil is an MCP (Microsoft Certified Professional) in Web Applications and Dot Net Framework.
Visit Akhil Mittal’s personal blog CodeTeddy (CodeTeddy ) for some good and informative articles. Following are some tech certifications that Akhil cleared,
• AZ-304: Microsoft Azure Architect Design.
• AZ-303: Microsoft Azure Architect Technologies.
• AZ-900: Microsoft Azure Fundamentals.
• Microsoft MCTS (70-528) Certified Programmer.
• Microsoft MCTS (70-536) Certified Programmer.
• Microsoft MCTS (70-515) Certified Programmer.

LinkedIn: https://www.linkedin.com/in/akhilmittal/
This is a Collaborative Group

780 members

Comments and Discussions

 
SuggestionVery useful and simple to understand Pin
Surendra Tarai5-Jun-18 2:06
Surendra Tarai5-Jun-18 2:06 
QuestionPlease write a article on In-Memory repository test for EF6 and MVC 4/5 Pin
Mou_kol19-Dec-17 0:49
Mou_kol19-Dec-17 0:49 
AnswerRe: Please write a article on In-Memory repository test for EF6 and MVC 4/5 Pin
Akhil Mittal19-Dec-17 2:48
professionalAkhil Mittal19-Dec-17 2:48 
Thanks. Will try.
Thanks
Happy Coding Smile | :)

QuestionHow people do the pagination when fetching user data Pin
Mou_kol19-Dec-17 0:48
Mou_kol19-Dec-17 0:48 
Questionwhat you mean about a sentence? Pin
Meh :D B@y@t8-Nov-17 7:29
professionalMeh :D B@y@t8-Nov-17 7:29 
QuestionHow to unit test user repository Pin
Tridip Bhattacharjee4-May-17 22:58
professionalTridip Bhattacharjee4-May-17 22:58 
AnswerRe: How to unit test user repository Pin
Akhil Mittal5-May-17 3:11
professionalAkhil Mittal5-May-17 3:11 
GeneralRe: How to unit test user repository Pin
Tridip Bhattacharjee9-May-17 2:08
professionalTridip Bhattacharjee9-May-17 2:08 
GeneralThanks Pin
Member 1256079316-Jun-16 4:52
Member 1256079316-Jun-16 4:52 
GeneralGood Explanation Pin
Alireza_13627-Mar-16 4:55
Alireza_13627-Mar-16 4:55 
Questionautomatic binding in controller parameters Pin
Member 118173808-Jul-15 11:02
Member 118173808-Jul-15 11:02 
AnswerRe: automatic binding in controller parameters Pin
Akhil Mittal8-Jul-15 19:11
professionalAkhil Mittal8-Jul-15 19:11 
QuestionMy Vote 5 Pin
Dharmesh .S. Patil2-Jul-15 1:37
professionalDharmesh .S. Patil2-Jul-15 1:37 
AnswerRe: My Vote 5 Pin
Akhil Mittal2-Jul-15 2:06
professionalAkhil Mittal2-Jul-15 2:06 
GeneralRe: My Vote 5 Pin
Dharmesh .S. Patil2-Jul-15 2:18
professionalDharmesh .S. Patil2-Jul-15 2:18 
QuestionAnother Layer Pin
cjb11027-Aug-14 23:46
cjb11027-Aug-14 23:46 
AnswerRe: Another Layer Pin
Akhil Mittal27-Aug-14 23:50
professionalAkhil Mittal27-Aug-14 23:50 
QuestionMy vote is 5 Pin
Mahsa Hassankashi10-Aug-14 7:21
Mahsa Hassankashi10-Aug-14 7:21 
AnswerRe: My vote is 5 Pin
Akhil Mittal10-Aug-14 18:13
professionalAkhil Mittal10-Aug-14 18:13 
AnswerRe: My vote is 5 Pin
Akhil Mittal18-May-15 18:57
professionalAkhil Mittal18-May-15 18:57 
GeneralRe: My vote is 5 Pin
Mahsa Hassankashi19-May-15 0:36
Mahsa Hassankashi19-May-15 0:36 
GeneralRe: My vote is 5 Pin
Akhil Mittal19-May-15 0:37
professionalAkhil Mittal19-May-15 0:37 
GeneralMy vote of 5 Pin
Prachi_G6-Jul-14 9:21
Prachi_G6-Jul-14 9:21 
GeneralMy vote of 5 Pin
Amey K Bhatkar15-Jan-14 0:51
Amey K Bhatkar15-Jan-14 0:51 
GeneralRe: My vote of 5 Pin
Akhil Mittal15-Jan-14 21:47
professionalAkhil Mittal15-Jan-14 21:47 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.