C# ASP.NET MVC中的NHibernate上下文会话

C# ASP.NET MVC中的NHibernate上下文会话,c#,.net,asp.net,asp.net-mvc,asp.net-mvc-2,C#,.net,Asp.net,Asp.net Mvc,Asp.net Mvc 2,我想在我的ASP.NET MVC 2应用程序中使用NHibernate的上下文会话,但我很难找到如何正确执行此操作的指导 我对每个请求的会话感兴趣。 您可以从wiki和那里的源代码学习实现,也可以从。更多关于S#arp的详细信息,包括会话管理说明。请告诉我我是否这样做了。以下是我的想法: Global.asax public class MvcApplication : NinjectHttpApplication { public MvcApplication() {

我想在我的ASP.NET MVC 2应用程序中使用NHibernate的上下文会话,但我很难找到如何正确执行此操作的指导

我对每个请求的会话感兴趣。


您可以从wiki和那里的源代码学习实现,也可以从。更多关于S#arp的详细信息,包括会话管理说明。

请告诉我我是否这样做了。以下是我的想法:

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;
    }
}
public类mvcapapplication:NinjectHttpApplication
{
公共mvcapapplication()
{
NHibernateProfiler.Initialize();
EndRequest+=委托{NHibernateHelper.EndContextSession(Kernel.Get());};
}
公共静态无效注册表项(路由收集路由)
{
routes.IgnoreRoute(“{resource}.axd/{*pathInfo}”);
routes.IgnoreRoute(“favicon.ico”);
routes.MapRoute(
“默认值”,//路由名称
“{controller}/{action}/{id}”,//带参数的URL
新建{controller=“Home”,action=“Index”,id=UrlParameter.Optional}//参数默认值
);
}
Application Started()上受保护的覆盖无效
{
RegisterAllAreas();
注册地址(RouteTable.Routes);
}   
受保护的覆盖IKernel CreateKernel()
{
StandardKernel内核=新的StandardKernel();
Load(AppDomain.CurrentDomain.GetAssemblies());
返回内核;
}
}
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();
            }
        }
    }
}
公共类NHibernateHelper
{
公共静态ISessionFactory CreateSessionFactory()
{
var nhConfig=新配置();
Configure();
流畅地返回。配置(nhConfig)
.Mappings(m=>
m、 FluentMappings.AddFromAssemblyOf()的
.Conventions.Add(ForeignKey.EndsWith(“Id”))
#如果调试
.ExposeConfiguration(cfg=>
{
新方案导出(cfg)
.SetOutputFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,“schema.sql”))
.创建(真、假);
})
#恩迪夫
.BuildSessionFactory();
}
公共静态ISession GetSession(ISessionFactory sessionFactory)
{
闭会期间会议;
if(CurrentSessionContext.HasBind(sessionFactory))
{
session=sessionFactory.GetCurrentSession();
}
其他的
{
session=sessionFactory.OpenSession();
CurrentSessionContext.Bind(会话);
}
返回会议;
}
公共静态void EndContextSession(ISessionFactory sessionFactory)
{
var session=CurrentSessionContext.Unbind(sessionFactory);
if(session!=null&&session.IsOpen)
{
尝试
{
if(session.Transaction!=null&&session.Transaction.IsActive)
{
//发生未处理的异常,不应进行db提交
session.Transaction.Rollback();
}
}
最后
{
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>()));
    }
}
公共类NHibernateModule:ninject模块
{
公共覆盖无效负载()
{
Bind().ToMethod(x=>NHibernateHelper.CreateSessionFactory()).InSingletonScope();
Bind().ToMethod(x=>NHibernateHelper.GetSession(Kernel.Get());
}
}

我们的做法与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));
}
...
我们的数据存储库我们有: 注意:(它不是一个存储库-我的设计错误:坏名字-,它更像你的NHibernateHelper,我想它更像某种NH配置包装器…)

会话工厂的问题是,您不想在每个请求上生成/构建一个。DataRepository充当单例,确保会话工厂只创建一次,并且在应用程序启动时创建。在我们的基本控制器中,我们使用WindosRCATLE将会话或sessionfactory注入控制器(一些控制器不需要数据库连接,因此它们派生自“无数据库”基本控制器)。我们的WindsorController工厂我们有:

...
//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);
    }
}
....
。。。
//建造师
公共风挡控制器工厂(ISessionFactory){
初始化();
//设置NHibernate的会话工厂
_集装箱。登记(
用于()的组件
.使用工厂法(
()=>会话工厂)
.生活方式
转瞬即逝的
);
}
私有void初始化(){
_容器=新WindsorContainer(
新的XML解释器(
新资源(“城堡”)
)
);
_container.AddFacility();
//还将所有控制器类型注册为瞬态
var controllerTypes=来自Assembly.getExecutionGassembly().GetTypes()中的t
其中typeof(IController).IsAssignableFrom(t)
选择t;
foreach(controllerTypes中的var t){
_container.AddComponentLifeStyle(t.FullName,t,LifestyleType.Transient);
}
}
....
通过这种设置,每个请求都会生成一个NHibernate会话,通过我们的设计,我们还可以拥有不生成会话的控制器。这就是我们目前的工作方式


我还可以说,我发现在尝试配置或调试我们遇到的问题时非常有用。

我没有注意到您需要ICurrentSessionContext,我认为任何“每个请求的会话”都可以。非常清晰的示例+1
...
//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);
    }
}
....