Контекстные сеансы NHibernate в ASP.NET MVC - PullRequest
6 голосов
/ 09 сентября 2010

Я хочу использовать контекстные сеансы NHibernate в моем приложении ASP.NET MVC 2, но мне трудно найти руководство о том, как правильно это сделать.

Меня интересует сеанс для запроса.

Ответы [ 3 ]

1 голос
/ 10 сентября 2010

Пожалуйста, дайте мне знать, если я делаю это правильно.Вот что я придумал:

Global.asax

public class MvcApplication : NinjectHttpApplication
{
    public MvcApplication()
    {
        NHibernateProfiler.Initialize();
        EndRequest += delegate { NHibernateHelper.EndContextSession(Kernel.Get<ISessionFactory>()); };            
    }

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.IgnoreRoute("favicon.ico");

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

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

    protected override IKernel CreateKernel()
    {
        StandardKernel kernel = new StandardKernel();
        kernel.Load(AppDomain.CurrentDomain.GetAssemblies());            
        return kernel;
    }
}

NHibernateHelper

public class NHibernateHelper
{
    public static ISessionFactory CreateSessionFactory()
    {
        var nhConfig = new Configuration();
        nhConfig.Configure();

        return Fluently.Configure(nhConfig)
            .Mappings(m =>
                m.FluentMappings.AddFromAssemblyOf<Reservation>()
                .Conventions.Add(ForeignKey.EndsWith("Id")))
#if DEBUG
            .ExposeConfiguration(cfg =>
            {
                new SchemaExport(cfg)
                    .SetOutputFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "schema.sql"))
                    .Create(true, false);
            })
#endif
            .BuildSessionFactory();
    }


    public static ISession GetSession(ISessionFactory sessionFactory)
    {
        ISession session;
        if (CurrentSessionContext.HasBind(sessionFactory))
        {
            session = sessionFactory.GetCurrentSession();
        }
        else
        {
            session = sessionFactory.OpenSession();
            CurrentSessionContext.Bind(session);
        }
        return session;
    }

    public static void EndContextSession(ISessionFactory sessionFactory)
    {
        var session = CurrentSessionContext.Unbind(sessionFactory);
        if (session != null && session.IsOpen)
        {
            try
            {
                if (session.Transaction != null && session.Transaction.IsActive)
                {
                    // an unhandled exception has occurred and no db commit should be made
                    session.Transaction.Rollback();
                }
            }
            finally
            {
                session.Dispose();
            }
        }
    }
}

NHibernateModule

public class NHibernateModule : NinjectModule
{
    public override void Load()
    {
        Bind<ISessionFactory>().ToMethod(x => NHibernateHelper.CreateSessionFactory()).InSingletonScope();
        Bind<ISession>().ToMethod(x => NHibernateHelper.GetSession(Kernel.Get<ISessionFactory>()));
    }
}
1 голос
/ 14 сентября 2010

Мы поступаем немного иначе, чем Бигглсби, и я не говорю, что он неправ, или что наш идеален.

В global.asax, который мы имеем при запуске приложения, имеем:

...
protected void Application_Start() {
    ISessionFactory sf =
        DataRepository
            .CreateSessionFactory(
                ConfigurationManager
                    .ConnectionStrings["conn_string"]
                    .ConnectionString
            );

//use windsor castle to inject the session 
ControllerBuilder
    .Current
    .SetControllerFactory(new WindsorControllerFactory(sf));
}
...

Наш DataRepository у нас есть: ПРИМЕЧАНИЕ: (это не репозиторий - моя ошибка проектирования: плохое имя - он больше похож на ваш NHibernateHelper, я думаю, это скорее своего рода оболочка конфигурации NH какого-то рода ...)

....
public static ISessionFactory CreateSessionFactory(string connectionString) {
   if (_sessionFactory == null){ 
    _sessionFactory = Fluently.Configure()
                .Database(MsSqlConfiguration ...
                    ... 
                    //custom configuration settings
                    ...
                    cfg.SetListener(ListenerType.PostInsert, new AuditListener());
                })
                .BuildSessionFactory();
    }
    return _sessionFactory;
}
....

С фабрикой сессий вы не хотите генерировать / создавать ее при каждом запросе. DataRepository действует как одноэлементный, гарантируя, что фабрика сеансов создается только один раз, и это при запуске приложения. В нашем базовом контроллере мы внедряем либо сессию, либо сессионную фабрику в наши контроллеры (некоторые контроллеры не требуют подключения к базе данных, поэтому они наследуются от базового контроллера «без базы данных»), используя WindosrCastle. Наш WindsorControllerFactory у нас есть:

...
//constructor
public WindsorControllerFactory(ISessessionFactory) {
    Initialize();

    // Set the session Factory for NHibernate
    _container.Register(
    Component.For<ISessionFactory>()
             .UsingFactoryMethod(
                  () => sessionFactory)
                  .LifeStyle
                  .Transient
             );
}

private void Initialize() {
    _container = new WindsorContainer(
                     new XmlInterpreter(
                         new ConfigResource("castle")
                     )
                 );
    _container.AddFacility<FactorySupportFacility>();

    // Also register all the controller types as transient
    var controllerTypes = from t in Assembly.GetExecutingAssembly().GetTypes()
                      where typeof(IController).IsAssignableFrom(t)
                      select t;

    foreach (var t in controllerTypes) {
        _container.AddComponentLifeStyle(t.FullName, t, LifestyleType.Transient);
    }
}
....

При такой настройке каждый запрос генерирует сеанс NHibernate, а благодаря нашему дизайну у нас также есть контроллеры, которые не генерируют сеансы. И это в настоящее время, как это работает для нас.

Могу ли я также сказать, что я нашел NHProf очень полезным при попытке настроить или отладить имеющуюся у нас проблему.

0 голосов
/ 09 сентября 2010

http://www.sharparchitecture.net

Вы можете узнать реализацию из вики и источников там, а также из здесь . Немного подробнее о S # arp здесь , включая объяснение управления сеансом.

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