Blog

Filter posts by Category Or Tag of the Blog section!

Repository Pattern practice in data access layer via entity framework

Friday, 14 December 2012

To read about definitions of Repository pattern refer to here or here and then let's begin! I'm gonna to show the using of repository pattern with entity framework in Data access layer. Sorry about the example because it's about product, category, brand, blah blah again! First of all, create an interface called IAggregateRoot

 

   public interface IAggregateRoot
    {
    }

 

It has no any member, you will find out what's that for later in this article, then create a generic type interface for introducing the most common operation used in enterprise DAL such as CRUD …

 

 public interface IRepository<T>
    {
        IEnumerable<T> GetAll();
        T FindBy(params Object[] keyValues);
        void Add(T entity);
        void Update(T entity);
        void Delete(T entity);
        void SaveChanges();
    }

 

Now create the Product class and derive it from or so-called implement the IAggregateRoot member for it!

 

    public class Product : IAggregateRoot
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
        public string Description { get; set; }
        public DateTime CreationTime { get; set; }
        public string Picture { get; set; }
    }

 

And now create the IProductRepository interface like this :

 

    public interface IProductRepository : IRepository<Product>
    {
    }

 

I have to notice that all we have done above are in the Model layer if you are using layered application, now refer to your DAL or Repository layer and create your DbContextClass:

 

   public class YourProjectContext : DbContext
    {
          public DbSet<Product> Product { get; set; }
    }

 

And now create the GenericRepoitory class like this :

 

    public class Repository<T> : IRepository<T> where T : class, IAggregateRoot
    {
        private readonly DbSet<T> _entitySet;
        private readonly YourProjectContext _yourProjectContext ;
        public Repository(YourProjectContext yourProjectContext )
        {
            _yourProjectContext = yourProjectContext ;
            _entitySet = yourProjectContext .Set<T>();
        }
        public IEnumerable<T> GetAll()
        {
            return _entitySet;
        }
        public T FindBy(params Object[] keyValues)
        {
            return _entitySet.Find(keyValues);
        }
        public void Add(T entity)
        {
            _entitySet.Add(entity);
        }
        public void Update(T entity)
        {
            _entitySet.Attach(entity);
           _yourProjectContext.Entry(entity).State=EntityState.Modified;
        }
        public void Delete(T entity)
        {
            var e = _yourProjectContext.Entry(entity);
            if (e.State == EntityState.Detached)
            {
                _yourProjectContext.Set<T>().Attach(entity);
                e = _yourProjectContext.Entry(entity);
            }
            e.State=EntityState.Deleted;   
        }
        public void SaveChanges()
        {
            _yourProjectContext.SaveChanges();
        }
    }

 

 you have all members of IRepository<T> implemented in this class, Now create the ProductRepository class like this :

 

    public class ProductRepository :Repository<Product>,IProductRepository
    {
      public ProductRepository(YourProjectContext yourProjectContext)
            : base(yourProjectContext)
        {
        }
    }

 

Now by calling IProductRepository interface in service or application layer, you have full access to the whole generic method of Repository and also for all members of ProductRepository, for example, spouse this service class

 

    public class ProductService : IProductService
    {
        private readonly IProductRepository _productRepository;
        public ProductService(IProductRepository productRepository)
        {
            _productRepository = productRepository;
        }
     }

 

You can access the repository members by _productRepository read-only field. I want to create a specific method in ProductRepository such as FindAllProductsByCategory  you have to first define it in IProductRepository :

 

    public interface IProductRepository : IRepository<Product>
    {
        IEnumerable<Product> FindAllProductsByCategory(Guid categoryId);
    }

 

And Then in ProductRepository, you have to implement the interface member

 

    public class ProductRepository :Repository<Product>,IProductRepository
    {
        private readonly StatosContext _statosContext;
        public ProductRepository(StatosContext statosContext)
            : base(statosContext)
        {
            _statosContext = statosContext;
        }
        public IEnumerable<Product> FindAllProductsByCategory(Guid categoryId)
        {
            var query =
                _statosContext.Product.Where(p => p.Category.Id == categoryId).OrderByDescending(p => p.CreationTime);
            return query.ToList();
        }

 

Thanks for reading!

Question!  is there any need to use the unit of work pattern when you using repository pattern with entity framework ??

Basically NOT because entity framework supports the UnitOfWork pattern and in other words, entity framework code first has been built based on UnitOfwork pattern and adding unitOfWork again is  typically redundant (because of using DbContext), but if want to have more control over disposal of context you can write your own IDbContextFactory and implement the unit of work pattern ! Cheers

comments powered by Disqus