Sunday, January 8, 2017

Repository Pattern

Repository Pattern separates the data access logic and maps it to the entities in the business logic by working with the domain entities and performing data access logic. The interaction between domain entities, data access logic and the business logic talk to each other using interfaces, and hides the details of data access from the business logic. In other words, business logic can access the data object without having knowledge of the underlying data access architecture.

Using this pattern, business logic is not aware whether the application is using LINQ to SQL or ADO.NET Entity Model ORM. In the future, underlying data sources or architecture can be changed without affecting the business logic.

Some advantages of using Repository Pattern are: Easy Domain driven development, can test business and database access logic separately, no duplication of code and maintainability of code is easy as data access logic is centralized.

Repository Pattern illustration:
As a First step we will create a base Entity interface with common properties, a Book Entity and a Base repository interfaces with CRUD operations
// Entity Base Interface with common properties
public interface IEntityBase
{
public int ID { get; set; }
public DateTime? CreateDate { get; set; }
public DateTime? ModifiedDate { get; set; }
}

// Base Repository Interface with CRUD operations
public interface IBaseRepository where T: IEntityBase
{
IEnumerable All();
T Create(T entity);
void Update(T entity);
T Delete(T entity);
int? Save();
}

// Book Entity implementing IEntityBase
public class Book : IEntityBase
{
public string Title { get; set;}
public decimal Price { get; set;}
}
Generic Implementation of Repository Pattern
Create BookRepository class by inheriting IBaseRepository as below:
public class BookRepository : IBaseRepository where T : IEntityBase
{
private DotNetLearningContext context;
protected readonly IDbSet _dbset;

public BookRepository(DotNetLearningContext context)
{
this.context = context;
this._dbset = context.Set();
}

public virtual IEnumerable All()
{
return _dbset.AsEnumerable();
}

public IEnumerable<T> FindBy(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
IEnumerable query = _dbset.Where(predicate).AsEnumerable();
return query;
}

public virtual T Create(T entity)
{
return context.Set().Add(entity);
}

public virtual void Update(T entity)
{
context.Entry(entity).State = System.Data.Entity.EntityState.Modified;
}

public virtual T Delete(T entity)
{
return context.Set().Remove(entity);
}

public async Task Save()
{
return await context.SaveChangesAsync();
}
}
You can use / call this repository class as below:
IBaseRepository bookRepository = new BookRepository();
var result = bookRepository.All;

foreach (var r in result)
{
Console.WriteLine(r.authorname);
}
Dependency Injection Implementation of Repository Pattern
Create BaseRepository class by inheriting IBaseRepository as below:
public class BaseRepository : IBaseRepository where T : IEntityBase
{
private DotNetLearningContext context;
protected readonly IDbSet _dbset;

public BaseRepository(DotNetLearningContext context)
{
this.context = context;
this._dbset = context.Set();
}

public virtual IEnumerable All()
{
return _dbset.AsEnumerable();
}

public IEnumerable<T> FindBy(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
IEnumerable query = _dbset.Where(predicate).AsEnumerable();
return query;
}

public virtual T Create(T entity)
{
return context.Set().Add(entity);
}

public virtual void Update(T entity)
{
context.Entry(entity).State = System.Data.Entity.EntityState.Modified;
}

public virtual T Delete(T entity)
{
return context.Set().Remove(entity);
}

public async Task Save()
{
return await context.SaveChangesAsync();
}
}
Using UnityContainer Register and Resolve Interface and Class implementations to make it available to use as Dependency Injection(s) as below in App/WebApiConfig classes:
// Dependency Injecor Resolvers
var container = new UnityContainer();

container.RegisterType(typeof(IBaseRepository<>), typeof(BaseRepository<>));

config.DependencyResolver = new UnityResolver(container);
Inject resolved repositories through controllers as below :
public class BookController
{
public BookController(IBaseRepository baseRepository)
: base(baseRepository)
{
// Call Base Repository Methods to use
}
}

No comments:

Post a Comment