I’m new to this Repository pattern and have seen lot of repository pattern + UoW implementations all over the internet and I’m not able to reach to a conclusion as to which of them is correct . After going through many links I’ve been able to implement one .
Considering the following points in mind
- It should satisfy SOLID principles
- Be testable
- Be independent of framework
- Be independent of DB
Here is the code of the implementation
Generic IRepository
public interface IRepository<T> where T : class { void Add(T entity); void Update(T entity); void Delete(T entity); T GetByKey(object id); }
RepositoryBase
public abstract class RepositoryBase<D, T> : IRepository<T> where T : class where D : BaseDbContext { private D dataContext; private readonly IDbSet<T> dbSet; protected IDbFactory<D> DbFactory { get; private set; } protected D DbContext { get { return dataContext ?? (dataContext = DbFactory.Init()); } } protected RepositoryBase(IDbFactory<D> dbFactory) { DbFactory = dbFactory; dbSet = DbContext.Set<T>(); } #region Implementation public virtual void Add(T entity) { dbSet.Add(entity); } public virtual void Update(T entity) { dbSet.Attach(entity); DbContext.Entry(entity).State = EntityState.Modified; } public virtual void Delete(T entity) { dbSet.Remove(entity); } public T GetByKey(object id) { return dbSet.Find(id); } #endregion }
IUnitofWork , UnitOfWork
public interface IUnitOfWork<D> where D : BaseDbContext { void Commit(); } public class UnitOfWork<D> : IUnitOfWork<D> where D : BaseDbContext, new() { private readonly IDbFactory<D> dbFactory; private D dbContext; public UnitOfWork(IDbFactory<D> dbFactory) { this.dbFactory = dbFactory; } public D DbContext { get { return dbContext ?? (dbContext = dbFactory.Init()); } } public void Commit() { DbContext.SaveChanges(); } }
IDBFactory ,DBFactory
public interface IDbFactory<D> where D : BaseDbContext { D Init(); } public class DbFactory<D> : Disposable, IDbFactory<D> where D : BaseDbContext, new() { D dbContext; public D Init() { return dbContext ?? (dbContext = new D()); } protected override void DisposeCore() { if (dbContext != null) dbContext.Dispose(); } }
BaseDbContext
public abstract class BaseDbContext : DbContext { public BaseDbContext(string nameOrConnectionString) : base(nameOrConnectionString) { } }
ProjectDbContext
public partial class ProjectDbContext : BaseDbContext { public ProjectDbContext() : base("name=ProjectDbContext") { Database.SetInitializer<ProjectDbContext>(null); } }
EXAMPLE USAGE
Controller
public class StudentsController : BaseController { private IStudentBusiness objstudentbusiness; public StudentsController(IStudentBusiness rstudentbusiness) { objstudentbusiness = rstudentbusiness; } public JsonResult LoadStudents() { var data = objstudentbusiness.ListStudents(); var jsonResult = Json(data, JsonRequestBehavior.AllowGet); return jsonResult; } }
IStudentBAL,StudentBAL
public interface IStudentBAL { void SaveStudent(StudentDto student); List<StudentDto> ListStudents(); } public class StudentBAL : BusinessBase, IStudentBAL { private readonly IStudentRepository objStudentRepository; private readonly IUnitOfWork<ProjectDbContext> objIUnitOfWork; public StudentBAL(IStudentRepository rIStudentRepository, IUnitOfWork<ProjectDbContext> rIUnitOfWork) { try { objStudentRepository = rIStudentRepository; objIUnitOfWork = rIUnitOfWork; } catch (Exception ex) { Log.Error(ex); } } public List<StudentDto> ListStudents() { try { var tusrs = objStudentRepository.ListStudents() ?? new List<StudentDto>(); return tusrs; } catch (Exception ex) { Log.Error(ex); } return new List<StudentDto>(); } }
IStudentRepository,StudentRepository
public interface IStudentRepository { void SaveStudent(Student Student); StudentDto GetStudentByName(StudentDto Studentname); Student GetStudentByID(int Studentid); List<StudentDto> ListStudents(); } public class StudentRepository : RepositoryBase<ProjectDbContext, Student>, IStudentRepository { public StudentRepository(IDbFactory<ProjectDbContext> dbFactory) : base(dbFactory) { } public List<StudentDto> ListStudents() { var students = (from t in DbContext.Students select new StudentDto { // all the required properties }).ToList(); return students; } }
- Dependency Injection is done using AutoFac
- Code for logging is omitted
I am asking if this seems like a good implementation or am I missing anything?
I would appreciate any feedback on my implementation you can offer regarding correctness, efficiency, and any suggestions. So here are my questions
- Is this loosely coupled ?
- Is it having any leaky abstraction and why ?
- What needs to be done to switch from EF to MySQL db and how much effort would it require to implement the changes?
- Is this pattern breaking any of the SOLID princples ,Law or Demeter or any Object Oriented laws?
- Does this pattern have any code redundancies which are not required ?
- How this architecture using EF would scale with a project containing more than 100+ domain entities and with each entity having at least more than 10 fields . Is it going to be maintenance nightmare later on?
-All criticisms greatly appreciated !!