2015-06-24 4 views
1

Я начинаю использовать Ninject в своем первом приложении MVC5. Вот мои NinjectWebCommon.cs:Ninject: объект объекта не может ссылаться на несколько экземпляров IEntityChangeTracker

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; 
     } 
    } 

Я попытался .InSingletonScope(), а также .InRequestScope(), но я все еще получаю «объект объект не может ссылаться несколько экземпляров IEntityChangeTracker» ошибки. Вот мой интерфейс:

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(); 
} 

Вот мой бетон:

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); 
    } 
} 

Вот контроллер (верхняя соответствующая часть):

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>(); 
    } 
... 

Не уверен, что я делаю неправильно, но при добавлении нового «Исполнительного» он бомбит ... Я понимаю, что он пытается использовать отдельные контексты, и это проблема, но я просто не знаю, как это исправить. По-видимому, линия в классе NinjectWebCommon.cs:

kernel.Bind<CMSContext>() 
       .ToSelf() 
       //.InSingletonScope(); 
       .InRequestScope(); 

Предполагается, что исправление, но это не так ... какие-либо идеи/предложения?

ответ

3

Вы должны использовать NuGet пакет Ninject.Web.Mvc, если вы еще не. Это настраивает ваше приложение, готовое использовать Ninject, кроме ваших привязок. Похоже, вы достаточно хорошо знакомы со связками вещей, которые я уже вижу в вашем методе CreateKernel().

Как только ваши привязки установлены, вы не должны создавать ядра в своих контроллерах, это потому, что библиотека Ninject.Web.Mvc настраивает Ninject для создания ваших контроллеров для вас под капотом. Поэтому любые зависимости, которые вы добавляете к ним, должны быть автоматически разрешены.

Таким образом, вы можете использовать конструктор инъекции решить ваши зависимости:

public class ExecutiveController : Controller 
{ 
    private IExecutiveRepository ExecutiveRepository; 
    private IUserRepository UserRepository; 
    private IExecutiveSectionRepository ExecutiveSectionRepository; 
    private IExecutiveSectionMappingRepository ExecutiveSectionMappingRepository; 
    private IContentRepository ContentRepository; 

    public ExecutiveController(
     IExecutiveRepository executiveRepository, 
     IUserRepository userRepository, 
     IExecutiveSectionRepository executiveSectionRepository, 
     IExecutiveSectionMappingRepository executiveSectionMappingRepository, 
     IContentRepository contentRepository) 
    { 

     // Set the field values 
     this.ExecutiveRepository = executiveRepository, 
     this.UserRepository = userRepository, 
     this.ExecutiveSectionRepository = executiveSectionRepository, 
     this.ExecutiveSectionMappingRepository = executiveSectionMappingRepository, 
     this.ContentRepository = contentRepository; 
    } 

    public ActionResult Index(int id) 
    { 
     // Use one of your dependencies... 
     var executive = this.executiveRepository.GetExecutiveById(id); 
    } 
} 

Или вы можете использовать атрибут [Inject] который имеет тот же эффект:

public class ExecutiveController : Controller 
{ 
    [Inject] 
    public IExecutiveRepository executiveRepository { get; set; } 

    [Inject] 
    public IUserRepository userRepository { get; set; } 

    [Inject] 
    public IExecutiveSectionRepository executiveSectionRepository { get; set; } 

    [Inject] 
    public IExecutiveSectionMappingRepository executiveSectionMappingRepository { get; set; } 

    [Inject] 
    public IContentRepository contentRepository { get; set; } 

    public ExecutiveController() 
    { 

    } 

    public ActionResult Index(int id) 
    { 
     // Use one of your dependencies... 
     var executive = this.executiveRepository.GetExecutiveById(id); 
    } 
} 
+0

Извините, я пропустил жизненно важный бит кода ... 1 сек. – Luke

+0

Я добавил // значение для значений полей теперь. .. он не работал бы без установки значений в контроллере. – Luke

+0

Фантастический. Большое спасибо.Я имел это раньше, но изучение шаблона Ninject AND repository сразу меня озадачило. Это более чем понятно. Ценить это! Отмечено. –

-1

Это может не ответить на вопрос. Но я предпочитаю использовать IDbContextFactory что EF предоставляет вам и сделать что-то вроде этого:

public interface IDefaultContextFactory : IDbContextFactory<CMSContext> {} 

public class DefaultContextFactory : IDefaultContextFactory 
{ 
    private readonly Lazy<CMSContext> lazyContext = new Lazy<CMSContext>(() => new CMSContext()); 

    public CMSContext Create() 
    { 
     return lazyContext.Value; 
    } 
} 

Тогда вы просто связать это, и когда требуется контекст вы можете сделать что-то вроде этого:

public class ExecutiveRepository : IExecutiveRepository, IDisposable 
{ 
    private readonly CMSContext context; 

    public ExecutiveRepository(IDefaultContextFactory contextFactory) 
    { 
     this.context = contextFactory.Create(); 
    } 
} 

Я считаю, @BatteryBackupUnit правильно, я бы также подумал об использовании вышеуказанного шаблона для контекстов.

+0

Yea не очень полезно, но Благодарю. Мне нужно использовать Ninject, как говорится в названии. –

+0

Что? Вы используете Ninject. Это лучший способ вставить контекст в ваши репозитории. На самом деле это агностик того, что вы используете для разработки Dependency Injection. –

+0

Мой офис/коллеги используют Ninject. Я ДОЛЖЕН использовать ninject. Не вариант/выбор. Это в названии. Если бы мой заголовок был «Я использую Ninject, но я хочу что-то неактуальное» ... тогда ваш ответ будет хорошим. Но это не так. –

2

Вы создаете ядро ​​для каждого контроллера.

InRequestScope обеспечивает только один экземпляр за запрос на ядро ​​.

Таким образом, вам необходимо адаптировать настройку ядра, так что есть только одно ядро ​​для каждого веб-приложения. См:

+0

«Адаптируйте свою настройку ядра» ... Вот как это получилось от NuGet. Все, что я сделал, это добавить эти связующие строки в файле NinjectwebCommon.cs. Просмотрев ссылки, которые вы предоставили, кажется, что между версией Nuget и тем, что вы предлагаете, существует раскол размером с каньон. Кажется, яблоки в Апельсины. Я не могу перейти от одного к другому –

+0

У меня появилось уведомление о том, что вы добавили еще больше, но это не показано в статье ... странно. В верхней части SO, если я нажму на значок с красным «1», он покажет вам, что вы сказали «Добавить OnActivation (x => {...})) к привязке. Добавьте к нему точку останова. что ... "... но в реальной статье я ничего не вижу ... ??? –

+0

@BatteryBackupUnit верен. Вы должны установить 'Ninject.Web.Mvc' в ваше приложение, а затем использовать методы инъекций в соответствии с рекомендациями, например, добавить атрибут' [Inject] 'или конструктор. Если вы создаете экземпляр ядра непосредственно в своем приложении MVC (кроме настройки привязок), вы делаете это неправильно. Ядро используется для настройки привязок к интерфейсам, а затем автоматически определяются зависимости. – Luke

 Смежные вопросы

  • Нет связанных вопросов^_^