Current System:
I am working on a project which is multi layered as shown below (in order of flow) and I am learning and trying to implement Repo Pattern with UOW on EF Database first.
- Service (Web API)
- Business (C# Class Library)
- Repository (Repo Pattern + UOW)
- ViewModels (Used by my Service for sent to my UI layer)
- Data (Entities)
- Database (SQL Server)
Repository:
Generic Repository:
public interface IRepository<TEntity> where TEntity : class
{
void Create(TEntity entity);
IQueryable<TEntity> ReadAll();
TEntity ReadById();
IQueryable<TEntity> Filter(Expression<Func<TEntity, bool>> predicate);
TEntity ReadSingle(Expression<Func<TEntity, bool>> predicate);
TEntity ReadSingleOrDefault(Expression<Func<TEntity, bool>> predicate);
void Delete(TEntity entity);
}
Repository Implementation:
internal class RepositoryBase<TEntity> : IRepository<TEntity> where TEntity : class
{
private bool _isDisposed;
private readonly DbSet<TEntity> _dbSet;
private Entities _entities;
public RepositoryBase(Entities entities)
{
this._entities = entities;
this._dbSet = _entities.Set<TEntity>();
}
public IQueryable<TEntity> ReadAll()
{
return _dbSet;
}
public TEntity ReadById()
{
// Dummy return. Don't worry about returning null will be implemented later.
return null;
}
public IQueryable<TEntity> Filter(System.Linq.Expressions.Expression<Func<TEntity, bool>> predicate)
{
return _dbSet.Where(predicate);
}
public TEntity ReadSingle(System.Linq.Expressions.Expression<Func<TEntity, bool>> predicate)
{
return _dbSet.Single(predicate);
}
public TEntity ReadSingleOrDefault(System.Linq.Expressions.Expression<Func<TEntity, bool>> predicate)
{
return _dbSet.SingleOrDefault(predicate);
}
public void Create(TEntity entity)
{
_dbSet.Add(entity);
}
public void Delete(TEntity entity)
{
_dbSet.Remove(entity);
}
public virtual void Dispose(bool isManuallyDisposing)
{
if (!_isDisposed)
{
if (isManuallyDisposing)
_tatwaEntities.Dispose();
}
_isDisposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~RepositoryBase()
{
Dispose(false);
}
Generic UOW:
public interface IUnitOfWork
{
IRepository<MyEntity> MyEntityRepository { get; }
//Other EntityRepositories
void SaveChanges();
}
UOW Implementation:
public class UnitOfWork : IUnitOfWork, IDisposable
{
private Entities _entities;
public UnitOfWork()
{
_entities = new entities();
}
private IRepository<MyEntity> _myEntityRepository;
public IRepository<MyEntity> MyEntityRepository
{
get
{
return _myEntityRepository ?? (_myEntityRepository = new RepositoryBase<MyEntity>(_entities));
}
}
public void SaveChanges()
{
_entities.SaveChanges();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_entities != null)
{
_entities.Dispose();
_entities = null;
}
}
}
}
Business Logic
public List<MyViewModel> ReadMyViewModelList()
{
var myVMList = new List<MyViewModel>();
using (var unitOfWork = new UnitOfWork())
{
userList.AddRange(unitOfWork.MyEntityRepository.ReadAll().Select(myEntity => new myViewModel
{
Prop1 = myEntity.Prop1,
Prop1 = myEntity.Prop2,
etc...
}));
}
return myVMList;
}
Problem:
- My problem now is that, in my business code, when i use UOW to get data, I have to cast MyEntity to MyViewModel which I think is wrong. because the whole idea of using Repo Pattern with UOW is to abstract and avoid DB/Entity dependency on the business code and be able to independently test that layer.
- I am creating an instance of my DBEntities in both ReposirotyBase and UOW implemntation classes, which again I think is wrong and should only be created once and I am not sure where is the best place and way yo create that instance.
- Is my architecture model the correct approach? If not can someone please suggest the appropriate changes to it so as to make it more testable, maintainable and sound.
Hope my question is elaborate. As I am in my learning phase of laying down architecture, I appreciate any additional suggestions/comments/improvements.
Cheers.