Castle Windsor LifestylePerWebRequest - 似乎只在ISession的第一个Web请求上解决

时间:2012-05-05 19:39:29

标签: asp.net-mvc-3 fluent-nhibernate castle-windsor

我正在设置我的MVC项目,以便在PerWebRequest的基础上解析ISession

这是我到目前为止所拥有的:

在我的Castle Windsor设置中,我使用工厂方法注册我的ISession

Component.For<ISession>().UsingFactoryMethod(ctx => MsSql2008SessionFactory.OpenSession()).LifestylePerWebRequest()

在我的Global.asax Application_Start()我每次请求开始时将ISession绑定到NHibernate的CurrentSessionContext

BeginRequest += delegate{
            CurrentSessionContext.Bind(
                     MsSql2008SessionFactory.OpenSession());
                       };

EndRequest += delegate{
             var session = MsSql2008SessionFactory
                             .SessionFactory
                               .GetCurrentSession();
              if (session != null)
              {
                session.Dispose();
              }
             CurrentSessionContext
                     .Unbind(MsSql2008SessionFactory
                         .SessionFactory);
        };

我第一次向页面发出请求时,一切正常。 我第二次向页面发出请求时会收到异常声明:

  

会话已结束!对象名称:'ISession'。

我做得不好?

2 个答案:

答案 0 :(得分:2)

这就是我做事的方式可能对你有用。我使用Fluent Nhibernate,以防一些配置没有jive。

public interface INHibernateSessionFactoryHelper
{
    ISessionFactory CreateSessionFactory();
}


public class NhibernateSessionFactoryHelper
{
    private static readonly string ConnectionString =
        ConfigurationManager.ConnectionStrings["SqlConnectionString"].ToString();

    public static ISessionFactory CreateSessionFactory()
    {
        return Fluently.Configure()
            .ProxyFactoryFactory("NHibernate.Bytecode.DefaultProxyFactoryFactory, NHibernate")
            .Mappings(m => m.FluentMappings.AddFromAssemblyOf<EntityMap>())
            .Database(
                MsSqlConfiguration.MsSql2008.ConnectionString(ConnectionString).AdoNetBatchSize(1000))
            .Cache(
                c =>
                c.ProviderClass<SysCacheProvider>().UseSecondLevelCache().UseQueryCache().UseMinimalPuts())
            .ExposeConfiguration(c => c.SetProperty(Environment.GenerateStatistics, "true")
                                          .SetProperty(Environment.SessionFactoryName, "My Session Factory")
                                          .SetProperty(Environment.CurrentSessionContextClass, "web"))
            .Diagnostics(d => d.Enable().OutputToFile(@"c:\temp\diags.txt"))
            .BuildSessionFactory();
    }
}

然后我的Windsor安装程序看起来像这样

public class NHibernateInstaller:IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(
            Component.For<ISessionFactory>().Instance(NhibernateSessionFactoryHelper.CreateSessionFactory()));
        container.Register(Component.For<ISessionManager>().ImplementedBy<SessionManager>().LifestylePerWebRequest());
    }
}

我省略了我使用的SessionManager的代码。如果您愿意,请告诉我

UPDTAE:这是我用来管理会话和事务的代码(我发现这些内容分散在互联网上但是它们都运行良好而没有太多修改.ISessionManager按照我之前的示例连接并注入到构造器中我的服务。

public interface ISessionManager : IDisposable
{
    ISession Session { get; set; }
    ISession GetSession();
}

public class SessionManager : ISessionManager
{
    private readonly ISessionFactory _sessionFactory;
    private TransactionScope _scope;
    public SessionManager(ISessionFactory sessionFactory)
    {
        _sessionFactory = sessionFactory;
    }

    #region ISessionManager Members

    public ISession Session { get; set; }

    public ISession GetSession()
    {
        if (Session == null)
        {
            Session = _sessionFactory.OpenSession();
            if (!CurrentSessionContext.HasBind(_sessionFactory))
            {
                _scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions {IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted});
                Session.BeginTransaction(IsolationLevel.ReadCommitted);
                CurrentSessionContext.Bind(Session);
            }
        }

        Session = _sessionFactory.GetCurrentSession();
        Session.FlushMode = FlushMode.Never;
        return Session;
    }


    public void Dispose()
    {
        if (CurrentSessionContext.HasBind(_sessionFactory))
        {
            CurrentSessionContext.Unbind(_sessionFactory);
        }
        try
        {
            Session.Transaction.Commit();
            _scope.Complete();
            _scope.Dispose();
            Session.Flush();
        }
        catch (Exception)
        {
            if (Session.Transaction != null && Session.Transaction.IsActive)
            {
                Session.Transaction.Rollback();
            }
            throw;
        }
        finally
        {
            Session.Close();
            Session.Dispose();
        }
    }

    #endregion
}

示例构造函数:

private readonly ISessionManager _sessionManager;
private readonly ISession _session;
 public UserService(ISessionManager sessionManager)
    {

        _sessionManager = sessionManager;
        _session = sessionManager.GetSession();

     }

答案 1 :(得分:2)

答案很简单。

我注入ISession的存储库具有Singleton生活方式。

这意味着在第一个请求上注入的ISession也被用于子请求(因为我的存储库类只是在应用程序的开头创建),因此已经被处理掉了。