Skip to content
July 14, 2012 / chadmeyercodez

Repository Pattern with Entity Framework

I recently started an initiative at work to move to one O/RM. Traditionally we have created our own custom way to access our data. It has worked for our needs but with the addition of Entity Framework 5.0, now seems like a good time to move to a technology that is backed by groups that maintain and enhance the technology. We also use the Repository Pattern in our architecture. It makes for a nice abstraction between data access and business logic along with making it easy to mock up in unit testing our controllers.

The example I will be talking about is in a git repo. I generated the Northwind database from Microsoft. I used the Entity Framework Power Tools in order to reverse engineer the database to code first POCO classes.

A BaseRepository is created to hold the DBContext and to handle disposing of the context. The thought process is this will allow change tracking to take care of changes in the entities and by default handle transactions.

public interface IBaseRepository {
    void Dispose();
    List RepositoryDatabaseErrors { get; set; }
}

public class BaseRepository : IBaseRepository, IDisposable {

    #region Constructor
    public BaseRepository() {
        this._databaseErrors = new List();
    }
    #endregion Constructor

    #region Properties
    private List _databaseErrors;
    public List RepositoryDatabaseErrors {
        get {
            if (_databaseErrors == null) {
                _databaseErrors = new List();
            }
            return _databaseErrors;
       }
       set { this._databaseErrors = value; }
    }

    private Web.Entity.NorthwindContext _dbContext = null;
    public Web.Entity.NorthwindContext DBContext {
        get {
            if (this._dbContext == null) {
                this._dbContext = new Entity.NorthwindContext();
            }
            return this._dbContext;
        }
    }
    #endregion Properties

    #region Dispose Methods

    ~BaseRepository() {
        Dispose(false);
    }

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

    protected virtual void Dispose(bool disposing) {
        if (this._dbContext != null) {
            this._dbContext.Dispose();
            this._dbContext = null;
        }
    }
    #endregion Dispose Methods
}

With the BaseRepository written, all other respoitories will inherit from the BaseRepository. Lets move on to the controller. For this example there is only one, HomeController. A Repository is created for the HomeController that will hold all the data access methods the controller actions need. It will consist of two methods, one to find all the employees in the northwind database and one to save the db context.

    #region Repository
    public interface IHomeRepository : IBaseRepository {
        List<Employee> FindEmployees();
        bool Save();
    }

    public class HomeRepository : BaseRepository, IHomeRepository {
        public List<Employee> FindEmployees() {
            return (from e in base.DBContext.Employees
                    select e).ToList();
        }

        public bool Save() {
            try {
                base.DBContext.SaveChanges();
                return true;
            }
            catch (System.Data.Entity.Validation.DbEntityValidationException ex) {
                foreach (DbEntityValidationResult result in ex.EntityValidationErrors) {
                    base.RepositoryDatabaseErrors.Add(result);
                }
                return false;
            }
        }
    }
    #endregion Repository

The controller will have a property called Repository so the controller actions can interact with the database. In the example, a list of employees is pulled from the database then all employees are updated with a first name and last name change. The purpose is to show that the entities dont need to be re attached to the data context. The DBContext change tracker will keep track of the changes that happen. When SaveChanges is called on the DBContext it will be able to see all changes that need to happen. This is the reason why the DBContext is opened on the base. If we were to new up a DBContext every time we call a method to the database, then we would have to attach the changed entities or find another way to save them. This way allows for all alterations to happen in the business logic and the database access happen in the repository.

    public class HomeController : BaseController {

        #region Properties
        public IHomeRepository Repository { get; set; }
        #endregion Properties

        #region Constructor
        public HomeController() {
            this.Repository = new HomeRepository();
        }
        #endregion Constructor

        public ActionResult Index() {

            List<Employee> employees = this.Repository.FindEmployees();

            // Updates the employees name, this will show that the change tracker of the DBContext 
            // picks up the changes so there is no need to attach them to the context
            employees.ForEach(delegate(Employee currentEmployee) {
                currentEmployee.FirstName = "Repository";
                currentEmployee.LastName = "EntityFramework";
            });

            if (!this.Repository.Save()) {
                foreach (DbEntityValidationResult result in this.Repository.RepositoryDatabaseErrors) {
                    foreach (DbValidationError error in result.ValidationErrors) {
                        this.ModelState.AddModelError("", error.ErrorMessage);
                    }
                }
            }

            return View();
        }

        #region Overrides
        protected override void Dispose(bool disposing) {
            // This is important. We must dispose the repository here in each controller
            this.Repository.Dispose();

            base.Dispose(disposing);
        }
        #endregion Overrides

    }

I really enjoy Entity Framework as an O/RM. One thing I would like to try to change is to move the dispose of the repository to the base controller so the dev does not have to remember to call dispose on each new controller. I will post an update when we figure something out.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: