Problem:
I use Ninject in my webapplication as IoC-Framework. I have tried to inject the Entity-Framework DbContext class to several classes in my code. I want to share a object instance by request. So I tried using the InRequestScope method from ninject. Problem is the instance is not shared. Instead I always get a new instance of DbContext.
Code:
First of all my implementation of DbContext class:
public class BudgetContext : DbContext, IUnitOfWork
{
public BudgetContext() : base("DefaultConnection")
{
Database.SetInitializer<BudgetContext>(new DropCreateDatabaseIfModelChanges<BudgetContext>());
}
public DbSet<Expense> Expenses { get; set; }
public int Commit()
{
return SaveChanges();
}
}
I want to inject the BudgetContext (my DbContext and also UnitOfWork) in two different places:
public class UnitOfWorkAttribute : ActionFilterAttribute
{
[Inject]
public IUnitOfWork UnitOfWork { get; set; } // injecting DbContext here (1)
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
base.OnActionExecuted(filterContext);
if (filterContext.Exception == null)
{
UnitOfWork.Commit();
}
}
}
public class ExpenseRepository : IExpenseRepository
{
private readonly BudgetContext context;
public ExpenseRepository(IUnitOfWork context) // injecting DbContext here (2)
{
this.context = (BudgetContext)context;
}
public void Add(Expense expense)
{
context.Expenses.Add(expense);
}
}
Both injected DbContext classes should be the same object instance for one request. My Ninject configuration in NinjectWebCommon.cs looks like this:
...
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUnitOfWork>().To<BudgetContext>().InRequestScope();
kernel.Bind<IExpenseRepository>().To<ExpenseRepository>();
// ...
kernel.Bind<ExpensesController>().To<ExpensesController>();
}
...
Did I configure the Ninject-Framework correct? What am I missing? Thanks for helping me out.
**Update:**
I have implemented a factory to create my UnitOfWork(which basically is my DbContext class). The implementation of the factory looks like this:
public class UnitOfWorkFactory : IUnitOfWorkFactory
{
private IUnitOfWork unitOfWork;
public IUnitOfWork Get()
{
if (unitOfWork == null)
unitOfWork = new BudgetContext();
return unitOfWork;
}
}
In Ninject I use the following configuration for the new factory:
kernel.Bind<IUnitOfWorkFactory>().To<UnitOfWorkFactory>().InRequestScope();
In my attribute I inject it this way:
[Inject]
public IUnitOfWorkFactory UnitOfWorkFactory{ get; set; }
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
base.OnActionExecuted(filterContext);
if (filterContext.Exception == null)
{
var unitOfWork = UnitOfWorkFactory.Get();
unitOfWork.Commit();
}
}
Unfortunately I have no success. My DbContext always gets resetted after it reaches the attribute class.