I am trying to implement a generic repository pattern. I found this site which I think its well explained. http://www.tugberkugurlu.com/archive/generic-repository-pattern-entity-framework-asp-net-mvc-and-unit-testing-triangle
My purpose is to save the developers some time and keystrokes and I know this will help me.
So I have 2 questions:
1. Is this a good approach or not, will I have some problems in the future?
2. How can I combine it with Unitofwork pattern?, I cant create an instance of the abstract class of course, so the following code its invalid.
public class UnitOfWork : IDisposable
{
#region Private fields
private readonly MyCompanyContext _context = new MyCompanyContext();
private GenericRepository<MyCompanyContext, Task> _taskRepository;
public GenericRepository<MyCompanyContext, Task> TaskRepository
{
get
{
return _taskRepository ??
(_taskRepository = new GenericRepository<MyCompanyContext, Task>());
}
}
namespace MyCompany.DAL.Repository
{
public interface IGenericRepository<T> where T : class
{
IQueryable<T> GetAll();
IQueryable<T> FindBy(Expression<Func<T, bool>> predicate);
void Add(T entity);
void Delete(T entity);
void Edit(T entity);
void Save();
}
public abstract class GenericRepository<C, T> :
IGenericRepository<T>
where T : class
where C : DbContext, new()
{
private C _entities = new C();
public C Context
{
get { return _entities; }
set { _entities = value; }
}
public virtual IQueryable<T> GetAll()
{
IQueryable<T> query = _entities.Set<T>();
return query;
}
public IQueryable<T> FindBy(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
IQueryable<T> query = _entities.Set<T>().Where(predicate);
return query;
}
public virtual void Add(T entity)
{
_entities.Set<T>().Add(entity);
}
public virtual void Delete(T entity)
{
_entities.Set<T>().Remove(entity);
}
public virtual void Edit(T entity)
{
_entities.Entry(entity).State = System.Data.EntityState.Modified;
}
public virtual void Save()
{
_entities.SaveChanges();
}
}
}
It is a data access pattern that prompts a more loosely coupled approach to data access. We create a generic repository, which 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.
Large-scale, complex projects benefit the most from readability improvments, and when using Dapper and C# the Dapper Base Repository pattern allows for better code readability and a single point of failure by creating a base class with generic methods that allow for querying and execution against a SQL database.
The unit of work class serves one purpose: to make sure that when you use multiple repositories, they share a single database context. That way, when a unit of work is complete you can call the SaveChanges method on that instance of the context and be assured that all related changes will be coordinated.
There are several opinions regarding repositories, but after trying various repository implementations in production for couple years myself, I agree with Ayende's opinion, that repository, especially generic, is redundant abstraction layer.
I liked very much this course: http://www.pluralsight-training.net/microsoft/Courses/TableOfContents/linq-architecture
It walked through most possible solutions and explained goods and bads.
What we're using right now is very thin abstraction over datacontext, just to overcome Linq2Sql testability issues, which are irrelevant in most cases when using EF.
With a lot of effort you might get that working, but I wonder if the effort is really worth it? I've seen implementations like this before, and they really struggle when attempting to manage many-to-many relationships (have a think about how you'd manage that in your scenario). You are using Entity Framework, an ORM right? ORMs like Entity Framework and nHibernate are designed to abstract the database implementation from application code, so what is the purpose of adding yet another abstraction above it to manage entities at such a granular level? If it's a question of testing, then you can use a mocking framework to mock the context, thus removing the need for an actual database during testing. If however, for architectural or security reasons you are seeking to remove interactions with a db context from your app code, I'd recommend for pragmatism using an implementation of the command pattern over the top of the entity framework. I've needed to do this on a larger scale enterprise (banking) application where for security reasons (rightly or wrongly) we were absolutely not allowed to have a db connection in our application code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With