Share via


Using Repository Pattern in Entity Framework

One of the most common pattern is followed in the world of Entity Framework is “Repository Pattern”. Since this is something which is heavily used and being practiced, I am not going to talk about the core pattern. Rather, try to show how one can implement it.

Objectives

As mentioned in https://msdn.microsoft.com/en-us/library/ff649690.aspx

  • 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.

Simple approach to ADO.NET Entity Framework

Let’s have one domain class called “Employee”

 public class Employee
{
    public int Id { get; set; }
    public string FullName { get; set; }
}

Now using this we will have a simple context class

 public class HRContext : DbContext
{        
    public DbSet<DomainClasses.Employee> Employees { get; set; }
}

After that, define the repository interface IEmployeeRepository

 public interface IEmployeeRepository : IDisposable
{
    IQueryable<Employee> All { get; }
    IQueryable<Employee> AllIncluding(params Expression<Func<Employee, object>>[] includeProperties);
    Employee Find(int id);
    void InsertOrUpdate(Employee employee);
    void Delete(int id);
    void Save();
}

Then the Repository class called EmployeeRepository

 public class EmployeeRepository : IEmployeeRepository
{
    HRContext context = new HRContext();
    public IQueryable<Employee> All
    {
        get { return context.Employees; }
    }
    public IQueryable<Employee> AllIncluding(params Expression<Func<Employee, object>>[] includeProperties)
    {
        IQueryable<Employee> query = context.Employees;
        foreach (var includeProperty in includeProperties) {
            query = query.Include(includeProperty);
        }
        return query;
    }
    public Employee Find(int id)
    {
        return context.Employees.Find(id);
    }
    public void InsertOrUpdate(Employee employee)
    {
        if (employee.Id == default(int)) {
            // New entity
            context.Employees.Add(employee);
        } else {
            // Existing entity
            context.Entry(employee).State = EntityState.Modified;
        }
    }
    public void Delete(int id)
    {
        var employee = context.Employees.Find(id);
        context.Employees.Remove(employee);
    }
    public void Save()
    {
        context.SaveChanges();
    }
    public void Dispose() 
    {
        context.Dispose();
    }
}

Then you should be implementing it in your apps (any type Windows or Web), like a Console Application

 namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            GetSomeEmployee();
        }
        private static void IntiateData()
        {
            using (var repo = new EmployeeRepository())
            {
                Employee em = new Employee() { FullName = "Wriju" };
                repo.InsertOrUpdate(em);
                repo.Save();
            }
        }
        private static void GetSomeEmployee()
        {
            using (var repo = new EmployeeRepository()) 
            {
                foreach (var emp in repo.All)
                {
                    Console.WriteLine("{0} - {1}", emp.Id, emp.FullName);
                }
            }            
        }
    }
}

This obviously simple approach. The recommended options are to make the Repository generic and handle the related entities. I will discuss about them later.

Namoskar!!!

Comments

  • Anonymous
    August 22, 2013
    Very Helpful
  • Anonymous
    August 25, 2013
    Your abstraction layer is leaky.When you are returning an IQueryable, it means, its end is open. the consumer is able to do whatever he wants to that expression and changing the propose of the method completely.
  • Anonymous
    August 25, 2013
    I don't agree with your implementation of InsertOrUpdate(...) - you're making the assumption that Id is int, and further also that the consumer hasn't set the value for Id yet. There are properties in EF that will let you handle this better.
  • Anonymous
    August 26, 2013
    I find that you are letting EF leak into your repository thinking.  For instance, InsertOrUpdate.  I prefer a simpler approach to my interfaces with a single Save(entity) method.  The code you have inside InsertOrUpdate would move inside Save along with the call to _context.SaveChanges().
  • Anonymous
    April 12, 2014
    Thanks
  • Anonymous
    May 14, 2014
    Very nice example, but there is no singleton for the context object. Could you help to modify using singleton for context. In the case we create many repositories, it would create many context objects
  • Anonymous
    June 17, 2014
    Thankq very much and it is very clear.
  • Anonymous
    August 02, 2014
    You might want to read this article for Ayende's criticism of this approach towards implementing the Repoistory pattern on top of Entity Framework (or indeed any ORM): "Architecting in the pit of doom: The evils of the repository abstraction layer" ayende.com/.../architecting-in-the-pit-of-doom-the-evils-of-the-repository-abstraction-layer
  • Anonymous
    August 28, 2014
    I don't understand why using this approach? actually your DbContext is the Unit Of Work and your repos are the DbSets. don't you think?
  • Anonymous
    January 21, 2015
    How about an example with WCF using Repository pattern? Also would you recommend using DI pattern for context of EF ie .. passing context of EF through constructor ?
  • Anonymous
    January 22, 2015
    Didn't he say the main aim of this document is to show how to implement Repository pattern not other things. Stop being picky.
  • Anonymous
    April 21, 2015
    I recommend reading this blog before implementing a repository on top of EF:www.reddnet.net/entity-framework-its-not-a-stack-of-pancakes
  • Anonymous
    May 19, 2015
    very simple and clear     that is way of teaching  many  thanks
  • Anonymous
    December 22, 2015
    how you can mock this repository if there is HRContext context = new HRContext(); and i saw many people said "thanks". it is more strange than your post...