다음을 통해 공유


Repository Pattern with ADO.NET Entity Framework Hack

Let’s build ADO.NET Entity Framework library using Repository Pattern. There are a many ways but this is probably the easiest hack. 

First build a blank solution

image

Then add a class library called “DAL” and add a class called “Employee”

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

Then in the DAL add “EntityFramework” from https://nuget.org in Package Manager Console

image

At Package manager Console it would show

image

Then add T4Scaffolding from https://nuget.org in Package Manager Console

image

The Package Manager Console would look like

image

Project structure will be as below

image

Notice that in the reference section the Entity Framework is showing but the “T4Scaffolding” is missing. However the packages.config shows the list.

This is as template so you will find them at the source folder

image

Run the following command from the DAL project’s Package Manager Console

 PM> scaffold repository DAL.Employee -DbContextType:HRContext

Output would show

image

This would create two files under DAL > Models as “EmployeeReopository.cs” and “HRContext.cs

image

The content would look like

HRContext.cs

 namespace DAL.Models
{
    public class HRContext : DbContext
    {
        // You can add custom code to this file. Changes will not be overwritten.
        // 
        // If you want Entity Framework to drop and regenerate your database
        // automatically whenever you change your model schema, add the following
        // code to the Application_Start method in your Global.asax file.
        // Note: this will destroy and re-create your database with every model change.
        // 
        // System.Data.Entity.Database.SetInitializer(new System.Data.Entity.DropCreateDatabaseIfModelChanges<DAL.Models.HRContext>());
        public DbSet<DAL.Employee> Employees { get; set; }
    }
}

EmployeeRepository.cs

 using System;
using System.Collections.Generic;

using System.Data;

using System.Data.Entity;

using System.Linq;

using System.Linq.Expressions;

using System.Web;

using DAL;
namespace DAL.Models
{ 
    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();
        }
    }
    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();
    }
}

You are simply done. You need a project and add DAL as reference then …

 namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            InsertEmployee();
        }
        private static void InsertEmployee()
        {
            using (var repo = new EmployeeRepository())
            {
                Employee em = new Employee() { FullName = "Wriju" };
                repo.InsertOrUpdate(em);
                repo.Save();
            }
        }
    }
}

No EntityFramework reference or so.

image

Isn’t it easy? Enjoy!!!

Special thanks to Julie Lerman, if you don’t know who she is then you are not an Entity Framework developer.

 

Namoskar!!!

Comments

  • Anonymous
    September 28, 2013
    Imagine I have already an edmx with dbcontext and Poco classes. Could I use the scaffolding to simply generate the repositories ? Thanks. paul.

  • Anonymous
    September 29, 2013
    Yes @Paul. It only generates Context class and Repository based on the exiting POCO. If you want to retain the existing Context you may do so.

  • Anonymous
    November 28, 2013
    There is a slight problem in your design. Suppose there is another repository .SalaryRepository. And both employee and salary needs to be added in one go! or in one single transaction. How would you do it? Ans: Unit of work pattern. Keep context outside repository and share among repositories

  • Anonymous
    February 24, 2014
    Your repositories are tightly coupled with the unit of work (HRContext context = new HRContext();). It's better to leave the creation of repositories to your unit of work and so let the repository instances know about it. Also when the save method is given to repository, you are kind of implementing the Active Object pattern, in which the complexity grows exponentially as the graph grows. Save is better to be on Unit Of Work too (so when you call .Save, the changes of the entire graph is saved). The third issue with this model is that it does not support navigation properties so a call like Person[0].Orders[0].Total will not be possible until you ignore the differed loading and load the entire graph to memory!