I am starting to use Ninject in my MVC5 code-first app. Here's my NinjectWebCommon.cs:
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
kernel.Bind<CMSContext>()
.ToSelf()
//.InSingletonScope();
.InRequestScope();
kernel.Bind<IExecutiveRepository>()
.To<ExecutiveRepository>();
kernel.Bind<IExecutiveSectionRepository>()
.To<ExecutiveSectionRepository>();
kernel.Bind<IExecutiveSectionMappingRepository>()
.To<ExecutiveSectionMappingRepository>();
kernel.Bind<IUserRepository>()
.To<UserRepository>();
kernel.Bind<IContentRepository>()
.To<ContentRepository>();
RegisterServices(kernel);
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
I tried .InSingletonScope() as well as .InRequestScope() but I still get the 'entity object cannot be referenced by multiple instances of IEntityChangeTracker' error. Here is my Interface:
public interface IExecutiveRepository : IDisposable
{
IEnumerable<Executive> GetExecutives();
Executive GetExecutiveById(int executiveId);
void InsertExecutive(Executive executive);
void UpdateExecutive(Executive executive);
void DeleteExecutive(int executiveId);
void Save();
}
Here is my concrete:
public class ExecutiveRepository : IExecutiveRepository, IDisposable
{
private CMSContext context;
public ExecutiveRepository(CMSContext context)
{
this.context = context;
}
public IEnumerable<Executive> GetExecutives()
{
return context.Executives.ToList();
}
public Executive GetExecutiveById(int id)
{
return context.Executives.Find(id);
}
public void InsertExecutive(Executive executive)
{
context.Executives.Add(executive);
}
public void DeleteExecutive(int executiveId)
{
Executive executive = context.Executives.Find(executiveId);
context.Executives.Remove(executive);
}
public void UpdateExecutive(Executive executive)
{
context.Entry(executive).State = EntityState.Modified;
}
public void Save()
{
context.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
Here is the controller(top pertinent part):
public class ExecutiveController : Controller
{
private IExecutiveRepository executiveRepository;
private IUserRepository userRepository;
private IExecutiveSectionRepository executiveSectionRepository;
private IExecutiveSectionMappingRepository executiveSectionMappingRepository;
private IContentRepository contentRepository;
private Ninject.IKernel _kernel = new StandardKernel();
//[Inject]
public ExecutiveController()
{
executiveRepository = _kernel.Get<ExecutiveRepository>();
userRepository = _kernel.Get<UserRepository>();
executiveSectionRepository = _kernel.Get<ExecutiveSectionRepository>();
executiveSectionMappingRepository = _kernel.Get<ExecutiveSectionMappingRepository>();
contentRepository = _kernel.Get<ContentRepository>();
}
...
Not sure what I am doing wrong but upon adding a new 'Executive' it bombs... I do understand it's trying to use separate contexts and that's the problem, but I 'm just not sure how to fix it. Apparently, the line in the NinjectWebCommon.cs class:
kernel.Bind<CMSContext>()
.ToSelf()
//.InSingletonScope();
.InRequestScope();
Is supposed to be the fix, but it isn't... any ideas/suggestions?
You should be using NUGET package
Ninject.Web.Mvc
if you aren't already. This configures your application ready to use Ninject, other than your bindings. It looks like you are reasonably familiar with the bindings side of things already from what I can see in yourCreateKernel()
method.Once your bindings are in place, you should not be creating Kernels in your controllers, this is because the
Ninject.Web.Mvc
library configures Ninject to create your controllers for you under the hood. Therefore any dependencies that you add to them should be automatically resolved.So, you can use constructor injection to resolve your dependencies:
Or you can use the
[Inject]
attribute which has the same effect: