I am facing a problem to save data using UnitOfWork. I mean I am unable to save data using UnitOFWork.Commit() from Controller class. My Implementation check bellow.
IUnitOfWork
public interface IUnitOfWork<C> : IDisposable
{
int Commit();
C GetContext { get; set; }
TransactionScope BeginTransaction();
}
UnitOfWork
public class UnitOfWork<C> : IUnitOfWork<C> where C : DbContext
{
private bool _disposed;
private readonly C _dbContext = null;
private TransactionScope _transaction;
public UnitOfWork()
{
GetContext = _dbContext ?? Activator.CreateInstance<C>();
}
public int Commit()
{
return GetContext.SaveChanges();
}
public C GetContext
{
get;
set;
}
public TransactionScope BeginTransaction()
{
if (null != _transaction)
{
_transaction = new TransactionScope();
}
return _transaction;
}
#region IDisposable Members
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
if (null != _transaction)
{
_transaction.Dispose();
}
if (null != _dbContext)
{
_dbContext.Dispose();
}
}
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
Now within GenericRepository
public abstract class RepositoryBase<C, E> : IRepository<E>
where E : class
where C : DbContext
{
private readonly IDbSet<E> _dbSet;
protected RepositoryBase(IUnitOfWork<C> unitOfWork)
{
UnitOfWork = unitOfWork;
_dbSet = UnitOfWork.GetContext.Set<E>();
}
protected IUnitOfWork<C> UnitOfWork
{
get;
private set;
}
#region IRepository<E> Members
public void Insert(E entity)
{
_dbSet.Add(entity);
UnitOfWork.GetContext.Entry(entity).State = System.Data.EntityState.Added;
UnitOfWork.Commit();
}
[...]
EmployeeRepository
public interface IEmployeeRepository : IRepository<EmployeeModel>
{
}
public class EmployeeRepository : RepositoryBase<MyDbContext, EmployeeModel>, IEmployeeRepository
{
public EmployeeRepository(IUnitOfWork<MyDbContext> unitOfWork)
: base(unitOfWork)
{
}
}
Note: If I call UnitOfWork.Commit() within GenericRepository described above everything fine. Data Saved successfully. But When I call UnitOfWork.Commit(); from Controller unable to save data. Check code bellow...
GenericRepository Insert Method
public void Insert(E entity)
{
_dbSet.Add(entity);
UnitOfWork.GetContext.Entry(entity).State = System.Data.EntityState.Added;
}
Now withing Controller
private readonly IEmployeeRepository _employeeRepository;
public EmployeeController(IEmployeeRepository employeeRepositoty, IUnitOfWork<MyDbContext> unitOfWork)
{
UnitOfWork = unitOfWork;
this._employeeRepository = employeeRepositoty;
}
[HttpPost]
public ActionResult Create(EmployeeModel employeemodel)
{
if (ModelState.IsValid)
{
using (UnitOfWork)
{
_employeeRepository.Insert(employeemodel);
UnitOfWork.Commit(); //OR UnitOfWork.GetContext.SaveChanges();
}
return RedirectToAction("Index");
}
return View(employeemodel);
}
I use Ninject as DI Framework. As a Said I am able to Save data , when I call UnitOfWork.Comit() within GenericRepository.
But when I want to use within Controller then unable to save data using UnitOfWork.commit(),
Di Configuration
kernel.Bind<IEmployeeRepository>().To<EmployeeRepository>().InRequestScope();
//For Unit Of Work
Kernrl.bind<IUnitOWork<MyDbContext>>.To<UnitOfWork>();
Or
kernel.Bind<IUnitOfWork<MyDbContext>>().To<MyDbContext>().InRequestScope();
Or
kernel.Bind<IUnitOfWork<MyDbContext>>().To<UnitOfWork<MyDbContext>>().InRequestScope();
I try all the above for UnitOfWork. But no luck :( . If I call Commit() from controller
unable to save data. But No error thrown.
So do you feel forcefully create of
GetContext = _dbContext ?? Activator.CreateInstance<C>(); is the problem ?
Because I already declare Kernrl.bind !!!
Please help me unable to understand the problem.
Probably Wrong DI (Ninject) Configuration create the problem. Solution check bellow.
kernel.Bind<IUnitOfWork<MyDbContext>>().To<UnitOfWork<MyDbContext>>().InRequestScope();
kernel.Bind<IEmployeeRepository>().To<EmployeeRepository>().InRequestScope();
Actualy I don't use .InRequestScope(); in my previous configuration. that's why It create mysterious behavior.
But Still unable to understand the reason behind that. Clarification welcome.
According the clarification (Problem: Since you use UnitOfWork both in your repository, and in your controller, you had two different instances, and each instance had its own context. So, you added the entities to one context (the one in your repository) but you called SaveChanges on a different context. Since that different context didn't have anything added to it, nothing happened.
Suggestion: you shouldn't need to make the repository InRequestScope, only the UnitOfWork, since that holds the context). Best solution check bellow.
kernel.Bind<IUnitOfWork<MyDbContext>>().To<UnitOfWork<MyDbContext>>().InRequestScope();
kernel.Bind<IEmployeeRepository>().To<EmployeeRepository>();