1

我使用 Spring.NET AOP 与 NHibernate 进行事务和会话管理。当用户太快提出多个请求时 - 延迟加载失败,异常“没有会话或会话已关闭”。

我在 NHibernate 配置中使用 SpringSessionContext 作为 CurrentSessionContext

public class FluentSessionFactory : LocalSessionFactoryObject
{
    protected override ISessionFactory NewSessionFactory(Configuration config)
    {
        var conf = Fluently
            .Configure()
            .Database(
                MsSqlConfiguration
                    .MsSql2008
                    .ConnectionString(c => c.FromConnectionStringWithKey("MyConnection"))
                    // TODO: use ExposeConfiguration method
                    .CurrentSessionContext<SpringSessionContext>()
                )
            .Mappings(
                m => m.FluentMappings
                    .AddFromAssembly(this.GetType().Assembly)
            )
            .BuildSessionFactory();
        return conf;
    }
}

在 xml 配置中:

<object id="SessionFactory" type="IndustryTracker.NHibernateRepository.FluentSessionFactory, IndustryTracker.NHibernateRepository">
    <property name="DbProvider" ref="DbProvider" />
</object>

和 OpenSessionInView 模块

<system.webServer>
    <validation validateIntegratedModeConfiguration="false"/>
    <modules runAllManagedModulesForAllRequests="true">
        <add name="OpenSessionInView"  type="Spring.Data.NHibernate.Support.OpenSessionInViewModule, Spring.Data.NHibernate31"/>
    </modules>
</system.webServer>

应用程序实现了从 db 获取实体的下一个工作流:视图 -> 控制器 -> 管理器 -> 存储库,与另一端相同。因此,会话是根据请求、事务 - 每次调用管理器创建的。

<object id="TransactionManager" type="Spring.Data.NHibernate.HibernateTransactionManager, Spring.Data.NHibernate31">
    <property name="DbProvider" ref="DbProvider"/>
    <property name="SessionFactory" ref="SessionFactory"/>
</object>

<tx:advice id="TxAdvice" transaction-manager="TransactionManager">
    <tx:attributes>
        <tx:method name="*"/>
    </tx:attributes>
</tx:advice>

<object id="Pointcut" type="Spring.Aop.Support.SdkRegularExpressionMethodPointcut, Spring.Aop">
    <property name="patterns">
        <list>
            <value>MyAppication.Managers.AccountManager</value>
            <value>MyAppication.Managers.CompanyManager</value>
        </list>
    </property>
</object>

<aop:config>
    <aop:advisor advice-ref="TxAdvice" pointcut-ref="Pointcut"/>
</aop:config>

这种行为的可能原因是什么,我该如何解决这个问题(Not.LazyLoad() 和 NHibernateUtil.Initialize() 在我的上下文中是不可接受的变体)?

4

2 回答 2

2

经过一番搜索,我发现问题出在配置中。配置中有spring WebSupportModule缺少http模块,所以正确的是:

    <httpModules>
      <add name="Spring" type="Spring.Context.Support.WebSupportModule, Spring.Web"/>
      <add name="OpenSessionInView" type="Spring.Data.NHibernate.Support.OpenSessionInViewModule, Spring.Data.NHibernate31"/>  
    </httpModules>

所以Marijn 是对的——它与弹簧的连接很弱。

于 2012-06-13T06:01:18.950 回答
1

1. 会话工厂配置为OpenSessionInViewModule

您可能忘记为以下对象配置会话工厂OpenSessionInViewModule

<appSettings>
  <add key="Spring.Data.NHibernate.Support.OpenSessionInViewModule.SessionFactoryObjectName" 
       value="SessionFactory"/>
</appSettings>

这必须在应用程序设置中完成。

2. 正确的基于 FluentNHibernate 的 spring session 工厂?

您似乎正在代码中配置会话工厂。您是否尝试过像文档和 BennyM的博客中描述的那样配置会话工厂?您的方法直接从 Fluent NHibernate 返回会话工厂,绕过所有 spring.net 支持。NewSessionFactory

3. 你的会话工厂事务知道吗?

<object id="SessionFactory" 
        type="IndustryTracker.NHibernateRepository.FluentSessionFactory, IndustryTracker.NHibernateRepository">
  <property name="DbProvider" ref="DbProvider" />
  <!-- provides integation with Spring's declarative transaction management features -->
  <property name="ExposeTransactionAwareSessionFactory" value="true" /> 
</object>

4. 你的控制器是否有有scope="application"或没有范围定义的依赖关系?

我可能一直在寻找错误的方向。如果您的控制器具有application范围依赖性,则意味着快速请求可能会干扰。默认值为"scope="application"; 所以你也想检查没有范围定义的合作者。请参阅有关web 范围的文档。

于 2012-06-11T14:43:16.763 回答