Thursday, February 19, 2015

Repository Pattern


Repository commonly refers to a storage location, often for safety or preservation.

Objectives of using repository
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.
Solution
Use a repository to separate the logic that retrieves the data and maps it to the entity model from the business logic that acts on the model. The business logic should be agnostic to the type of data that comprises the data source layer. For example, the data source layer can be a database, a SharePoint list, or a Web service.
The repository mediates between the data source layer and the business layers of the application. It queries the data source for the data, maps the data from the data source to a business entity, and persists changes in the business entity to the data source. 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.
The repository pattern is an abstraction. Its purpose is to reduce complexity and make the rest of the code persistent ignorant. As a bonus it allows you to write unit tests instead of integration tests. The problem is that many developers fail to understand the patterns purpose and create repositories which leak persistence specific information up to the caller (typically by exposing IQueryable<T>, read through Mark Seemann’s blog  IQueryable is Tight Coupling ).
The Repository Pattern is a common construct to avoid duplication of data access logic throughout our application. This includes direct access to a database, ORM, WCF dataservices, xml files and so on.  We can easily query the repository for data objects, without having to know how to provide things like a connection string. The repository behaves like a freely available in-memory data collection to which we can add, delete and update objects.
The Repository pattern adds a separation layer between the data and domain layers of an application. It also makes the data access parts of an application better testable. Using repositories is not about being able to switch persistence technology (i.e. changing database or using a web service etc instead).
Creating Repository is not as tough as it sounds to be, once you implement this by your own, you’ll love it for sure.

Create Repository pattern
Step1 Very first thing to create a repository is to define an interface inside which we declare CRUD operations on entity.
using System;
using System.Linq;
using System.Linq.Expressions;

namespace Demo.Repositories
{
    public interface IRepository
    {
        void Insert(T entity);
        void Delete(T entity);
        List<T> SearchFor(Expression<Func<T, bool>> predicate);
        List<T> GetAll();
        T GetById(int id);
    }
}

Step2 Create a class inheriting the interface, pretty straight forward approach. 
using System;
using System.Data.Linq;
using System.Linq;
using System.Linq.Expressions;

namespace Demo.Repositories
{
    public class Repository<T> : IRepository<T> where T : class, IEntity
    {
        protected Table<T> DataTable;

        public Repository(DataContext dataContext)
        {
            DataTable = dataContext.GetTable<T>();
        }

        #region IRepository<T> Members

        public void Insert(T entity)
        {
            DataTable.InsertOnSubmit(entity);
        }

        public void Delete(T entity)
        {
            DataTable.DeleteOnSubmit(entity);
        }

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

        public IQueryable<T> GetAll()
        {
            return DataTable;
        }

        #endregion
    }

}

Now the major part of our job is done.

Step 3 Use the repository in the application
using System;
using System.Collections.Generic;
using System.Linq;
using Demo.Repositories;

namespace LinqToSqlRepositoryConsole
{
    internal class Program
    {
        private static void Main()
        {
            using (var dataContext = new HotelsDataContext())
            {
                var hotelRepository = new Repository<Hotel>(dataContext);
                var cityRepository = new Repository<City>(dataContext);

                City city = cityRepository
                    .SearchFor(c => c.Name.StartsWith("Mum"))
                    .Single();

                IEnumerable<Hotel> orderedHotels = hotelRepository
                    .GetAll()
                    .Where(c => c.City.Equals(city))
                    .OrderBy(h => h.Name);

                Console.WriteLine("* Hotels in {0} *", city.Name);

                foreach (Hotel orderedHotel in orderedHotels)
                {
                    Console.WriteLine(orderedHotel.Name);
                }

                Console.ReadKey();
            }
        }
    }
}

Now that we have most of the things ready we can refine our functionality as per our choice, add more entity specific operations.

No comments:

Post a Comment

Application of TOGAF in actual software development/ SDLC

As a TOGAF certified professional, I often encounter misconceptions about the framework's applicability in standard software development...