2010-06-04 3 views
4

В настоящее время у моего репозитория есть 2 конструктора. Когда я называю это с моего веб-сайта mvc, я всегда вызываю первый конструктор и тем самым открываю новый сеанс. Должен ли я проходить сессию. Как я должен это делать.nhibernate: Управление сеансом репозитория

public CompanyRepository() 
    { 
     _session = NHibernateHelper.OpenSession(); 
    } 

    public CompanyRepository(ISession session) 
    { 
     _session = session; 
    } 




public class NHibernateHelper 
    { 
     private static ISessionFactory _sessionFactory; 

     private static ISessionFactory SessionFactory 
     { 
      get 
      { 
       if (_sessionFactory == null) 
       { 
        var configuration = new Configuration(); 
        configuration.Configure(); 
        configuration.AddAssembly(typeof(UserProfile).Assembly); 
        configuration.SetProperty(NHibernate.Cfg.Environment.ConnectionStringName, 
               System.Environment.MachineName); 
        _sessionFactory = configuration.BuildSessionFactory(); 
       } 
       return _sessionFactory; 
      } 
     } 

     public static ISession OpenSession() 
     { 
      return SessionFactory.OpenSession(); 
     } 
    } 

Я использую контейнер Ninject IOC (очень новый для меня). У меня есть следующий контейнер. Как связать ISession с CompanyRepository.

private class EStoreDependencies : NinjectModule 
     { 
      public override void Load() 
      { 
       Bind<ICompanyRepository>().To<CompanyRepository>(); 
       Bind<IUserProfileRepository>().To<UserProfileRepository>(); 
       Bind<IAddressRepository>().To<AddressRepository>(); 
       Bind<IRolesService>().To<AspNetRoleProviderWrapper>(); 
       Bind<IUserService>().To<AspNetMembershipProviderWrapper>(); 
       Bind<ICurrentUserSerivce>().To<DefaultCurrentUserSerivce>(); 
       Bind<IPasswordService>().To<AspNetMembershipProviderWrapper>(); 
       Bind<IStatusResponseRepository>().To<StatusResponseRepository>(); 
       Bind<ICategoryRepository>().To<CategoryRepository>(); 
       Bind<IProductRepository>().To<ProductRepository>(); 
      } 
     } 

ответ

3

Вы должны использовать «один сеанс для каждого запроса» образец, путем сохранения объекта ISession в HttpContext и обмена его между хранилищами и запросов, сделанных в течение того же запроса HTTP.

Вот implementation using MVC action attributes.

Простая/базовая реализация также может быть достигнута путем простого изменения вашего класса NHibernateHelper как это:

public class NHibernateHelper { 
    //... 

    const string SessionKey = "NhibernateSessionPerRequest"; 

    public static ISession OpenSession(){ 
     var context = HttpContext.Current; 

     if(context != null && context.Items.ContainsKey(SessionKey)){ 
      //Return already open ISession 
      return (ISession)context.Items[SessionKey]; 
     } 
     else{ 
      //Create new ISession and store in HttpContext 
      var newSession = SessionFactory.OpenSession(); 
      if(context != null) 
       context.Items[SessionKey] = newSession; 

      return newSession; 
     } 
    } 
} 

код не был ни скомпилирован, ни испытания ... должен работать, однако.

0

Используйте инверсию управления контейнера

1

Ваш код или, предпочтительно, инъекции зависимость должна всегда проходить ISession в конструктор репозитория. Это позволяет нескольким репозиториям участвовать в одной транзакции.

I вторая рекомендация Paco, чтобы позволить платформе инъекций зависимостей обрабатывать это для вас. Проблема с этим подходом заключается в не-веб-приложениях, которые не имеют чистых границ работы, таких как цикл HTTP-запроса-ответа. У нас есть хранилища, которые совместно используются приложениями Windows Forms и ASP.NET, и мы вручную управляем созданием репозиториев в приложениях Windows Forms.

+0

Я так думал, я использую ninject (добавленный код выше). Как связать сессию с CompanyRepository. Извините, все это еще не нажал. – frosty

+1

'Bind (). (). WithConstructorArgument (" session ", NHibernateHelper.OpenSession());' Есть, вероятно, другие способы сделать это. –

0

Попробуйте использовать sessionFactory.GetCurrentSession(), который позволит вам получить доступ к contextual session.

Это позволит вам использовать модель «сеанс для каждого запроса», как описано в другом ответе, без необходимости самим этим кодом. Вы даже можете выбрать, какой у вас контекст: Http (как предлагает ваш пример) или куча других (я использую CallSessionContext для моего модульного теста).