簡體   English   中英

ASP.NET MVC中的NHibernate上下文會話

[英]NHibernate Contextual Sessions in ASP.NET MVC

我想在我的ASP.NET MVC 2應用程序中使用NHibernate的Contextual Sessions,但是我很難找到如何正確執行此操作的指導。

我對每個請求的Session感興趣。

如果我以正確的方式這樣做,請告訴我。 這是我想出的:

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

我們對bigglesby的態度略有不同,我並不是說他的錯,或者說我們是完美的。

在我們有應用程序啟動的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充當單例,確保會話工廠僅創建一次,並且在應用程序啟動時。 在我們的基本控制器中,我們將會話或sessionfactory注入我們的控制器(某些控制器不需要數據庫連接,因此它們來自“無數據庫”基本控制器),使用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非常有用。

http://www.sharparchitecture.net

您可以從wiki和源代碼中學習實現,也可以從這里學習 更多第#ARP細節有點這里 ,包括會話管理的解釋。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM