Как я могу решить это? Я хочу внедрить сеанс nhibernate, но сеанс еще не создан - PullRequest
1 голос
/ 16 января 2011

Редактировать

Я хотел бы попытаться сделать то, что рекомендовал Remo Gloor

  1. Создать производный SessionFactoryProvider для провайдера, который выполняет повторный запуск SessionFactory с использованием кодав OnApplicationStarted
  2. Создайте привязку для SessionFactory с использованием нового поставщика и поместите его в SingletonScope
  3. Создайте SessionProvider, производный от Provider, который получает SessionFactory, внедренный в конструктор, и повторно запускает новый сеанс с помощью GetCurrentSession ofфабрика.
  4. Создайте привязку для сеанса к указанному выше провайдеру с действиями активации и деактивации, которые открывают, передают, откатывают и закрывают сеанс (в основном код из Application_BeginRequest, EndRequest).Деклярируйте привязку, как в области запроса.
  5. Удалить Application_BeginRequest, EndRequest.
  6. Привязать репо с помощью Bind (). To ();

Я ищуучебник, который затрагивает эти вопросы с файлом, который я могу скачать и поиграть.Если он использует много шаблонов, вы должны быть достаточно подробными, так как они все равно меня поймут.


Привет

Я пытаюсь выполнить сеанс по запросу с моим nhibernate.

Я сделал это в моем global.aspx

using System;
using System.Web.Mvc;
using System.Web.Routing;
using Demo.WebUI.Models.NinjectModules;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate;
using NHibernate.Context;
using Ninject;
using Ninject.Modules;
using Ninject.Web.Mvc;


namespace Demo.WebUI
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : NinjectHttpApplication
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new {controller = "Account", action = "Login", id = UrlParameter.Optional} // Parameter defaults
                );
        }

        public static ISessionFactory SessionFactory { get; private set; }

        protected override void OnApplicationStarted()
        {
            AreaRegistration.RegisterAllAreas();
            RegisterRoutes(RouteTable.Routes);

            SessionFactory = Fluently.Configure()
                .Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("test")))
                .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Demo.Framework.Data.NhibernateMapping.UserMap>())
                .ExposeConfiguration(x => x.SetProperty("current_session_context_class", "web"))
                .ExposeConfiguration(BuidSchema)
                .BuildSessionFactory();
        }


        protected void Application_BeginRequest(object sender, EventArgs e)
        {
            ISession session = SessionFactory.OpenSession();
            session.BeginTransaction();
            CurrentSessionContext.Bind(session);
        }

        protected void Application_EndRequest(object sender, EventArgs e)
        {
            ISession session = CurrentSessionContext.Unbind(SessionFactory);

            if (session != null)
            {
                try
                {
                    session.Transaction.Commit();
                }
                catch (Exception)
                {
                    session.Transaction.Rollback();
                }
                finally
                {
                    session.Close();
                    session.Dispose();
                }
            }
        }


        protected override IKernel CreateKernel()
        {
            var modules = new INinjectModule[]
                              {
                                  new ServiceModule(),
                                  new RepoModule()
                              };

            return new StandardKernel(modules);
        }

        private static void BuidSchema(NHibernate.Cfg.Configuration config)
        {
            new NHibernate.Tool.hbm2ddl.SchemaExport(config).Create(false, true);
        }
    }
}

В моем RepoModule у меня есть

Bind<IUserRepo>().To<UserRepo>().WithConstructorArgument("session",MvcApplication.SessionFactory.GetCurrentSession());

Это вызовет ошибку, потому что ninject создаст ядро ​​до того, как OnApplicationStarted () запуститсяи до того, как Application_Begin начнет связывать его.

Так что мне делать?

Редактировать

Это то, что я нашел в каком-то уроке.

  public static ISessionFactory SessionFactory { get; private set; }

        public MvcApplication()
        {
            SessionFactory = CreateSessionFactory();
        }

        private static ISessionFactory CreateSessionFactory()
        {
            return Fluently.Configure()
            .Database(MsSqlConfiguration.MsSql2008.ConnectionString(c => c.FromConnectionStringWithKey("test")))
            .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Demo.Framework.Data.NhibernateMapping.UserMap>())
            .ExposeConfiguration(x => x.SetProperty("current_session_context_class", "web"))
            .ExposeConfiguration(BuidSchema)
            .BuildSessionFactory();
        }

Мое связывание

  Bind<IUserRepo>().To<UserRepo>();
    Bind<ISession>().ToMethod(x => MvcApplication.SessionFactory.GetCurrentSession());

Поэтому я сначала создаю фабрику сеансов при загрузке конструктора, а затем привязываю ее к Isession вместо передачи в качестве параметра.

Единственная вещь, в которой я не уверен с глобальным aspx - это если он будет постоянно вызывать конструктор и воссоздавать SessionFactory, что плохо.Поэтому я не уверен, нужно ли мне сначала проверить, существует ли он.

Ответы [ 4 ]

2 голосов
/ 23 января 2011

Недавно я писал в блоге об использовании nhibernate в mvc-приложении asp.net с шаблоном репозитория.Этот проект предоставляет пример использования nhibernate & ninject.Вот несколько ссылок:

http://blog.bobcravens.com/2010/07/using-nhibernate-in-asp-net-mvc/

http://blog.bobcravens.com/2010/06/the-repository-pattern-with-linq-to-fluent-nhibernate-and-mysql/

http://blog.bobcravens.com/2010/09/the-repository-pattern-part-2/

http://blog.bobcravens.com/2010/11/using-ninject-to-manage-critical-resources/

Я думаючто у нас похожая архитектура.Посмотрите на сообщения и дайте мне знать, если у вас есть какие-либо вопросы.

Кстати, вы можете скачать этот проект по адресу http://gpsnerd.codeplex.com

Боб

2 голосов
/ 17 января 2011

Ваша реализация хороша, но не является хорошим решением, так как вы выполняете ручное управление жизненным циклом сеанса.Фактический способ сделать это - позволить Ninject решать, когда сеанс создается, открывается, закрывается и удаляется.

Например, представьте себе действия, в которых вам не нужен сеанс.Или более крупный проект, где у вас есть несколько баз данных и сеансов, чтобы разделить нагрузку.В этих ситуациях вы не хотите, чтобы все возможные сеансы создавались для каждого действия, поскольку это означает, что можно избежать накладных расходов.Вы скорее хотите, чтобы были созданы только те, которые требуются для текущего действия.

Для этого требуется несколько изменений:

  1. Создайте производный SessionFactoryProvider для провайдера, который перезапускает SessionFactory, используякод в OnApplicationStarted
  2. Создайте привязку для SessionFactory с использованием нового поставщика и поместите ее в SingletonScope
  3. Создайте SessionProvider, производный от Provider, который получает SessionFactory, внедренный в конструктор, и повторно запускает новый сеанс, используяGetCurrentSession для фабрики.
  4. Создайте привязку для ISession к указанному выше провайдеру с действиями активации и деактивации, которые открывают, передают, откатывают и закрывают сеанс (в основном код из Application_BeginRequest, EndRequest).Удалите привязку, как в области запроса.
  5. Удалите Application_BeginRequest, EndRequest.
  6. Привязайте репо, используя Bind<IUserRepo>().To<UserRepo>();
1 голос
/ 16 января 2011

Оберните код инициализации SessionFactory в одноэлементный файл, который будет инициализировать и настраивать фабричный сеанс один раз при доступе к свойству Instance.Используйте это в BeginRequest вместо текущего кода.

0 голосов
/ 16 января 2011

Вы используете текущий контекст сеанса, вам не нужно вводить сеанс!

Вместо этого введите SessionFactory, затем используйте GetCurrentSession(), чтобы получить ISession.

* 1006.* После этого изменения вы можете использовать решение Феличе.
...