Thursday 1 January 2015

Repository Design Pattern

Projects are accessing data from various sources from database, flat files to web services. The business layer of any particular application consumes these accessed data in order to utilize in business logic. The separation of concerns and the testability plays major role when we are accessing data from various sources. The Repository design pattern provides us generic solutions to these problems. Data access is not the only place where we can use the repository pattern, but is the most used domain of this particular design pattern.


Following diagram depicts a bird’s eye view of how the repositories do the linkage between the data source and the business layer. The Business logic would access in memory data from the repositories rather than accessing the physical data source directly. And this clearly separates the physical data access technologies and business logic technologies. 

Following is an example of how to implement the employee repository. Starting with the interface.

  public interface IEmployeeRepo
    {
        void Add(Employee newEmp);
        void Update(Employee emp);
        void Remove(Employee emp);
        IList<Employee> Search(Expression<Func<Employee, bool>> predicate);
        Employee GetById(int empId);
    }

Even though I have written the update method in this interface, it is unlikely that in a real production system that we are having this kind of individual update method. Mostly, we are using the UOW design pattern for the atomic updates in the repositories.

The Search function is also using a LINQ predicate in order to enable the calling entity to use LINQ queries for search features. 

Following is an example of how to use this Interface when we need to dealt with the Employee entity.
 
public class WorkingClass
    {
        public void DoWork(IEmployeeRepo repository)
        {
            repository.Add(new Employee());
            repository.Search(x => x.Name == "James");
            repository.GetById(23);
        }
    }

We need to create these repositories for each and every entity in the application. Which is leading to a maintenance problem. Hence it is advisable to create Generic repository to handle operations rather than create repositories for each and every entity.

 Following is a Sample Interface for a generic repository.

  public interface IRepository<T>
                    where T : class, IEntity
    {
        IQueryable<T> FindAll();
        IQueryable<T> Search(Expression<Func<T, bool>> predicate);
        T GetById(int id);       
        void Add(T newEntity);
        void Remove(T entity);
    }

We are using the generic type T to represent entities in repository.

Following is the concrete implementation of the IRepository.

public class RepositoryImpl<T> : IRepository<T>
                                    where T : class, IEntity {

        public RepositoryImpl(ObjectContext context) {
            _objectSet = context.CreateObjectSet<T>();
        }

       public IQueryable<T> Search (Expression<Func<T, bool>> predicate) {
            return _objectSet.Where(predicate);
        }

        public void Add(T newEntity) {
            _objectSet.AddObject(newEntity);
        }

        public void Remove(T entity) {
            _objectSet.DeleteObject(entity);
        }

        public IQueryable<T> FindAll()
        {
            return _objectSet;
        }

        public T GetById(int id)
        {
            return _objectSet.Single(x => x.Id == id);
        }

        protected ObjectSet<T> _objectSet;
    }

You can see that the object context playing a big role when creating the repository instance. This is the actual entity framework context we are using here to connect to the database.  We can see that how it is converted the EF specific operations on objects based on the required method. 

One thing to note in GetById method, it requires the attribute Id contains on each and every entity that we are dealing with. This is achieved using the IEntiry interface which make sure all the inherited entities consist of id attribute.

  public interface IEntity {
        int Id { get; }
    }

Following depicts how we can use the IRepository implementation in a worker class. As an example, I am using a web controller class.

public class WorkerController : Controller
    {      
        public WorkerController()
            :this(new SqlUnitOfWork())
        {
           
        }

        public WorkerController(IUnitOfWork unitOfWork)
        {
            _unitOfWork = unitOfWork;
            _repository = _unitOfWork.Employees;
        }       

        public ViewResult Index()
        {
            var model = _repository.FindAll()                                  
                                   .OrderBy(e => e.dateRegistered);
            return View(model);
        }


        public ViewResult Details(int id)
        {
            var model = _repository.FindById(id);

            return View(model);
        }

      

        [HttpPost]
        public ActionResult Edit(int id, FormCollection collection)
        {
            var model = _repository.FindById(id);
            TryUpdateModel(model, new[] { "FirstName", "dateRegistered" });
            if (ModelState.IsValid)
            {
                _unitOfWork.Commit();
                return RedirectToAction("Index");
            }

            return View(model);
        }

        private readonly IUnitOfWork _unitOfWork;
        private readonly IRepository<Employee> _repository;
    }

I have used the Unit Of Work pattern to perform transactions against the db. You can find how the UOW is implemented in this post.

Ultimately , you can see that the controller class do not need to bother about how this data been actually accessed by the respective repository. This is the real power of this repository pattern. 

No comments:

Post a Comment