Difference between revisions of "Repository Pattern"

From Logic Wiki
Jump to: navigation, search
(useful paging sample which can be implemented in custom repository)
 
(4 intermediate revisions by the same user not shown)
Line 2: Line 2:
 
[[Category:CSharp]]
 
[[Category:CSharp]]
 
[[Category:ASP.NET]]
 
[[Category:ASP.NET]]
 +
 
Reporsitory pattern is a layer between application and data storage. With this pattern application doesn't need to know how to delete, update or write data to database.
 
Reporsitory pattern is a layer between application and data storage. With this pattern application doesn't need to know how to delete, update or write data to database.
  
 
== In a nutshell ==
 
== In a nutshell ==
* Add(obj)
 
* Remove(obj)
 
 
* Get(id)
 
* Get(id)
 
* GetAll()
 
* GetAll()
 
* Find(predicate)
 
* Find(predicate)
  
Sample pattern :
+
* Add(obj)
 +
* AddRange(obj)
  
using System;
+
* Remove(obj)
using System.Linq;
+
* RemoveAll(obj)
using System.Linq.Expressions;
+
 
  namespace Remondo.Database.Repositories
+
 
 +
== Sample pattern ==
 +
=== Interface ===
 +
<pre class="brush:csharp;">
 +
using System;
 +
using System.Collections.Generic;
 +
using System.Linq;
 +
using System.Linq.Expressions;
 +
 
 +
  namespace Queries.Core.Repositories
 
   {
 
   {
     public interface IRepository<T>
+
     public interface IRepository<TEntity> where TEntity : class
 
     {
 
     {
         void Insert(T entity);
+
         TEntity Get(int Id);
         void Delete(T entity);
+
         IEnumerable<TEntity> GetAll();
         IQueryable<T> SearchFor(Expression<Func<T, bool>> predicate);
+
         IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate);
         IQueryable<T> GetAll();
+
 
         T GetById(int id);
+
         void Add(TEntity entity);
 +
        void AddRange(IEnumerable<TEntity> entities);
 +
 
 +
        void Remove(TEntity entity);
 +
         void RemoveAll(IEnumerable<TEntity> entities);
 +
       
 
     }
 
     }
 
  }
 
  }
The generic GetById() method explicitly needs all our entities to implement the IEntity interface. This is because we need them to provide us with an Id property to make our generic search for a specific Id possible.
+
</pre>
 +
=== Generic Implementation  ===
 +
<pre class="brush:csharp;">
 +
using System;
 +
using System.Collections.Generic;
 +
using System.Data.Entity;
 +
using System.Linq;
 +
using System.Linq.Expressions;
 +
using System.Web;
 +
using Spv.Api.Core.IDataAccess;
  
namespace Remondo.Database
+
namespace Spv.Api.Core.DataAccess
{
+
{
     public interface IEntity
+
     public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
 
     {
 
     {
         int ID { get; }
+
         protected readonly DbContext Context;
    }
+
}
+
  
Since we already have LINQ to SQL entities with an Id property, declaring the IEntity interface is sufficient. Since these are partial classes, they will not be overridden by LINQ to SQL code generation tools.
+
       
 +
        public Repository(DbContext context)
 +
        {
 +
            Context = context;
 +
        }
  
namespace Remondo.Database
+
        public TEntity Get(int Id)
{
+
        {
    partial class City : IEntity
+
            return Context.Set<TEntity>().Find(Id);
    {
+
        }
    }
+
+
    partial class Hotel : IEntity
+
    {
+
    }
+
}
+
  
Sample Implementation
+
        public IEnumerable<TEntity> GetAll()
 +
        {
 +
            return Context.Set<TEntity>().ToList();
 +
        }
  
using System;
+
        public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
using System.Data.Entity;
+
using System.Linq;
+
using System.Linq.Expressions;
+
+
namespace Remondo.Database.Repositories
+
{
+
    public class Repository<T> : IRepository<T> where T : class
+
    {
+
        protected DbSet<T> DbSet;
+
+
        public Repository(DbContext dataContext)
+
 
         {
 
         {
             DbSet = dataContext.Set<T>();
+
             return Context.Set<TEntity>().Where(predicate);
 
         }
 
         }
+
 
        #region IRepository<T> Members
+
         public void Add(TEntity entity)
+
         public void Insert(T entity)
+
 
         {
 
         {
             DbSet.Add(entity);
+
             Context.Set<TEntity>().Add(entity);
 
         }
 
         }
+
 
         public void Delete(T entity)
+
         public void AddRange(IEnumerable<TEntity> entities)
 
         {
 
         {
             DbSet.Remove(entity);
+
             Context.Set<TEntity>().AddRange(entities);
 
         }
 
         }
+
 
         public IQueryable<T> SearchFor(Expression<Func<T, bool>> predicate)
+
         public void Remove(TEntity entity)
 
         {
 
         {
             return DbSet.Where(predicate);
+
             Context.Set<TEntity>().Remove(entity);
 
         }
 
         }
+
 
         public IQueryable<T> GetAll()
+
         public void RemoveAll(IEnumerable<TEntity> entities)
 +
        {
 +
            Context.Set<TEntity>().RemoveRange(entities);
 +
        }
 +
    }
 +
}
 +
</pre>
 +
 
 +
=== Custom Repository Interface ===
 +
<pre class="brush:csharp;">
 +
using System.Collections.Generic;
 +
using Spv.Api.Models;
 +
using Spv.Models;
 +
 
 +
namespace Spv.Api.Core.IDataAccess
 +
{
 +
    public interface IDealRepository : IRepository<Deal>
 +
    {
 +
        IEnumerable<DealModel> GetAllDealModels();
 +
        DealModel GetDealModelById(int id);
 +
    }
 +
}
 +
</pre>
 +
=== Custom Repository ===
 +
<pre class="brush:csharp;">
 +
using System;
 +
using System.Collections.Generic;
 +
using System.Linq;
 +
using System.Web;
 +
using Spv.Api.Core.IDataAccess;
 +
using Spv.Api.Models;
 +
using Spv.Models;
 +
 
 +
namespace Spv.Api.Core.DataAccess
 +
{
 +
    public class DealRepository : Repository<Deal>, IDealRepository
 +
    {
 +
        public DealRepository(SpvDbContext context) : base(context)
 
         {
 
         {
            return DbSet;
 
 
         }
 
         }
 
   
 
   
         public T GetById(int id)
+
         IEnumerable<DealModel> IDealRepository.GetAllDealModels()
 
         {
 
         {
             return DbSet.Find(id);
+
             return SpvDbContext.Deals.Select(x=> new DealModel(x)).ToList();
 +
        }
 +
 
 +
        public DealModel GetDealModelById(int id)
 +
        {
 +
            var deal = SpvDbContext.Deals.FirstOrDefault(x => x.Id == id);
 +
            return deal == null ? null : new DealModel(deal);
 +
        }
 +
 
 +
        public SpvDbContext SpvDbContext
 +
        {
 +
            get { return Context as SpvDbContext;}
 
         }
 
         }
        #endregion
 
 
     }
 
     }
  }
+
}
 +
</pre>
 +
==== useful paging sample which can be implemented in custom repository ====
 +
<pre class="brush:csharp;">
 +
public IEnumerable<Deal> GetSomeDeals(int pageIndex, int pagesSize = 10)
 +
{
 +
  return SpvDbContext.Deals
 +
  .Include(c => c.Author)
 +
  .OrderBy(c => c.Name)
 +
  .Skip((pageIndex - 1) * pageSize)
 +
  .Take(pageSize)
 +
  .ToList();
 +
}
 +
</pre>
 +
 
 +
== Generic Repository Pattern ==
 +
[[File:GenericRepository.JPG]]
 +
 
 +
 
 +
-----------------
 +
See Also : [[Unit Of Work Pattern]]

Latest revision as of 16:35, 14 June 2017


Reporsitory pattern is a layer between application and data storage. With this pattern application doesn't need to know how to delete, update or write data to database.

In a nutshell

  • Get(id)
  • GetAll()
  • Find(predicate)
  • Add(obj)
  • AddRange(obj)
  • Remove(obj)
  • RemoveAll(obj)


Sample pattern

Interface

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

 namespace Queries.Core.Repositories
  {
    public interface IRepository<TEntity> where TEntity : class
    {
        TEntity Get(int Id);
        IEnumerable<TEntity> GetAll();
        IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate);

        void Add(TEntity entity);
        void AddRange(IEnumerable<TEntity> entities);

        void Remove(TEntity entity);
        void RemoveAll(IEnumerable<TEntity> entities);
        
    }
 }

Generic Implementation

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
using Spv.Api.Core.IDataAccess;

namespace Spv.Api.Core.DataAccess
{
    public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
    {
        protected readonly DbContext Context;

        
        public Repository(DbContext context)
        {
            Context = context;
        }

        public TEntity Get(int Id)
        {
            return Context.Set<TEntity>().Find(Id);
        }

        public IEnumerable<TEntity> GetAll()
        {
            return Context.Set<TEntity>().ToList();
        }

        public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
        {
            return Context.Set<TEntity>().Where(predicate);
        }

        public void Add(TEntity entity)
        {
            Context.Set<TEntity>().Add(entity);
        }

        public void AddRange(IEnumerable<TEntity> entities)
        {
            Context.Set<TEntity>().AddRange(entities);
        }

        public void Remove(TEntity entity)
        {
            Context.Set<TEntity>().Remove(entity);
        }

        public void RemoveAll(IEnumerable<TEntity> entities)
        {
            Context.Set<TEntity>().RemoveRange(entities);
        }
    }
}

Custom Repository Interface

using System.Collections.Generic;
using Spv.Api.Models;
using Spv.Models;

namespace Spv.Api.Core.IDataAccess
{
    public interface IDealRepository : IRepository<Deal>
    {
        IEnumerable<DealModel> GetAllDealModels();
        DealModel GetDealModelById(int id);
    }
}

Custom Repository

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Spv.Api.Core.IDataAccess;
using Spv.Api.Models;
using Spv.Models;

namespace Spv.Api.Core.DataAccess
{
    public class DealRepository : Repository<Deal>, IDealRepository
    {
        public DealRepository(SpvDbContext context) : base(context)
        {
        }
 
        IEnumerable<DealModel> IDealRepository.GetAllDealModels()
        {
            return SpvDbContext.Deals.Select(x=> new DealModel(x)).ToList();
        }

        public DealModel GetDealModelById(int id)
        {
            var deal = SpvDbContext.Deals.FirstOrDefault(x => x.Id == id);
            return deal == null ? null : new DealModel(deal);
        }

        public SpvDbContext SpvDbContext
        {
            get { return Context as SpvDbContext;}
        }
    }
}

useful paging sample which can be implemented in custom repository

public IEnumerable<Deal> GetSomeDeals(int pageIndex, int pagesSize = 10)
{
 return SpvDbContext.Deals
  .Include(c => c.Author)
  .OrderBy(c => c.Name)
  .Skip((pageIndex - 1) * pageSize)
  .Take(pageSize)
  .ToList();
}

Generic Repository Pattern

GenericRepository.JPG



See Also : Unit Of Work Pattern