nhibernate: управление сессиями репозитория - PullRequest
4 голосов
/ 04 июня 2010

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

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

Ответы [ 4 ]

3 голосов
/ 04 июня 2010

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

Вот реализация с использованием атрибутов действия MVC .

Легкая / базовая реализация также может быть достигнута простым изменением вашего класса 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;
        }
    }
}

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

1 голос
/ 04 июня 2010

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

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

0 голосов
/ 06 июня 2010

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

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

0 голосов
/ 04 июня 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...