使用asp mvc 3、nhibernate 3.2和spring.net 1.3.2时出现“没有与线程绑定的Hibernate Session”异常。

4

我正在使用ASP.Net MVC 3、spring.net 1.3.2和nhibernate 3.2。我一直在努力让Web应用程序在IIS 7.5中运行。它在Visual Studio 2010内部运行良好。

我遇到的错误是

No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here 
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: NHibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here

Source Error: 

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.  

Stack Trace: 


[HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here]
   Spring.Data.NHibernate.SpringSessionContext.CurrentSession() in c:\_prj\spring-net\trunk\src\Spring\Spring.Data.NHibernate12\Data\NHibernate\SpringSessionContext.cs:72
   Technolog.Rma.Business.Repositories.RepairBatchDAO.findRepairBatchPageCount(String login, Int32 rowsPerPage) in C:\work\samplemvc\src\Technolog.Rma.Business\Repositories\RepairBatchDAO.cs:55
   _dynamic_Technolog.Rma.Business.Repositories.RepairBatchDAO.findRepairBatchPageCount(Object , Object[] ) +273
   Spring.Reflection.Dynamic.SafeMethod.Invoke(Object target, Object[] arguments) in c:\_prj\spring-net\trunk\src\Spring\Spring.Core\Reflection\Dynamic\DynamicMethod.cs:156
   Spring.Aop.Framework.DynamicMethodInvocation.InvokeJoinpoint() in c:\_prj\spring-net\trunk\src\Spring\Spring.Aop\Aop\Framework\DynamicMethodInvocation.cs:100
   Spring.Dao.Support.PersistenceExceptionTranslationInterceptor.Invoke(IMethodInvocation invocation) in c:\_prj\spring-net\trunk\src\Spring\Spring.Data\Dao\Support\PersistenceExceptionTranslationInterceptor.cs:181

<snip/>

我的 web.config 文件是

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=152368

  Spring.Context.Support.ContextHandler, Spring.Core

    <resource uri="~/Config/propertyConfigurer.xml" />
  -->
<configuration>
  <configSections>
    <sectionGroup name="spring">
      <section name="context" type="Spring.Context.Support.MvcContextHandler, Spring.Web.Mvc3" />
    </sectionGroup>
  </configSections>
  <appSettings>
    <add key="dataFile" value="App_Data\data.db3" />
    <add key="ClientValidationEnabled" value="true"/>
    <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
    <add key="Spring.Data.NHibernate.Support.OpenSessionInViewModule.SessionFactoryObjectName" value="SessionFactory"/>
  </appSettings>
  <spring>
    <context>
      <resource uri="file://~/Config/propertyConfigurer.xml" />
      <resource uri="file://~/Config/sessionFactory.xml" />
      <resource uri="file://~/Config/mappers.xml" />
      <resource uri="file://~/Config/repositories.xml" />
      <resource uri="file://~/Config/controllers.xml" />
      <resource uri="file://~/Config/scopedobjects.xml" />
      <resource uri="file://~/Config/utils.xml" />
    </context>
  </spring>
  <system.web>
    <httpModules>
      <!--
      <add name="Spring" type="Spring.Context.Support.WebSupportModule, Spring.Web"/>
      <add name="OpenSessionInView" type="Spring.Data.NHibernate.Support.OpenSessionInViewModule, Spring.Data.NHibernate32"/> 
      -->
    </httpModules>
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      </assemblies>
    </compilation>
    <pages>
      <namespaces>
        <add namespace="System.Web.Helpers" />
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
        <add namespace="System.Web.WebPages" />
      </namespaces>
    </pages>
    <authentication mode="Forms">
      <forms loginUrl="~/Account/LogOn" timeout="2880" />
    </authentication>
    <customErrors mode="Off"/>

  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <modules runAllManagedModulesForAllRequests="true">
      <add name="Spring" type="Spring.Context.Support.WebSupportModule, Spring.Web"/>
      <add name="OpenSessionInView" type="Spring.Data.NHibernate.Support.OpenSessionInViewModule, Spring.Data.NHibernate32"/>
    </modules>
    <!--
    <handlers>
      <add name="SpringPageHandler" verb="*" path="*.aspx" type="Spring.Web.Support.PageHandlerFactory, Spring.Web"/>
      <add name="SpringWebServiceHandler" verb="*" path="*.asmx" type="Spring.Web.Services.WebServiceHandlerFactory, Spring.Web" />
      <add name="SpringContextMonitor" verb="*" path="ContextMonitor.ashx" type="Spring.Web.Support.ContextMonitor, Spring.Web"/>
    </handlers>
    -->
  </system.webServer>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.7.0" newVersion="4.0.7.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

我的sessionFactory.xml文件是:

<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net" 
         xmlns:db="http://www.springframework.net/database"
         xmlns:tx="http://www.springframework.net/tx">

  <object
    id="siteRoot"
    type="System.Web.Hosting.HostingEnvironment, System.Web"
    factory-method="get_ApplicationPhysicalPath" />

  <object
    id="dataFile"
    type="System.IO.Path, mscorlib"
    factory-method="Combine">
    <constructor-arg name="path1" ref="siteRoot" />
    <constructor-arg name="path2" value="${dataFile}" />
  </object>

  <db:provider id="dbProvider"
               provider="System.Data.SqlClient"
               connectionString="Data Source=AJASQL7;Initial Catalog=Xanadu;User ID=RMA;Password=RMA;"/>


  <object id="sessionFactory" scope="application" type="Spring.Data.NHibernate.LocalSessionFactoryObject, Spring.Data.NHibernate32">
    <property name="DbProvider" ref="dbProvider"/>
    <property name="MappingAssemblies">
      <list>
        <value>Technolog.Rma.Business</value>
      </list>
    </property>
    <property name="HibernateProperties">
      <dictionary>
        <entry key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider"/>
        <entry key="dialect" value="NHibernate.Dialect.MsSql7Dialect"/>
        <entry key="connection.driver_class" value="NHibernate.Driver.SqlClientDriver"/>
        <entry key="use_proxy_validator" value="false" />
        <entry key="current_session_context_class" value="Spring.Data.NHibernate.SpringSessionContext, Spring.Data.NHibernate32"/>
      </dictionary>
    </property>

  </object>

  <!-- Transaction Management Strategy - local database transactions -->

  <object id="transactionManager"
        type="Spring.Data.NHibernate.HibernateTransactionManager, Spring.Data.NHibernate32">
    <property name="DbProvider" ref="dbProvider"/>
    <property name="SessionFactory" ref="sessionFactory"/>
  </object>

  <!-- Exception translation object post processor -->
  <object type="Spring.Dao.Attributes.PersistenceExceptionTranslationPostProcessor, Spring.Data"/>

</objects>

我的 RepairBatchDao 的一部分是

[Repository]
class RepairBatchDAO : IRepairBatchDAO
{

    public ISessionFactory SessionFactory { get; set; }

    public long findRepairBatchPageCount(string login, int rowsPerPage)
    {
        var rowCount = 1L;
        var session = SessionFactory.GetCurrentSession(); // line 55
        var transaction = session.BeginTransaction();
        try
        {
            transaction = session.BeginTransaction();
            var hqlCountQuery = session.CreateQuery("select count(*) from Technolog.Rma.Business.Domain.RepairBatch rb where rb.Customer.Login=?")
                            .SetParameter(0, login);
            rowCount = hqlCountQuery.UniqueResult<long>();
            transaction.Commit();
            return (rowCount + rowsPerPage - 1) / rowsPerPage;
        }
        catch
        {
            if (transaction != null) transaction.Rollback();
        }
        finally
        {
            if (session != null) session.Close(); // I shouldn't be doing this...
        }

        return 0L;

    }

    // snip ...

我花了太多时间尝试自己解决这个问题。我希望有人可以指导我正确的方向。我已经查看了各种stackoverflow帖子(太多了无法一一列举),但它们并没有帮助。

我是一个Java程序员,这是我的第一个.net项目,所以不确定我是否做了什么傻事。

2012年9月25日

我已经对我的customerDAO进行了更改。

 public class CustomerDAO : ICustomerDAO
    {

        public ISessionFactory SessionFactory { get; set; }

        private TransactionTemplate tt;

        public IPlatformTransactionManager  TransactionManager
        {
            set { tt = new TransactionTemplate(value); }
        }
 <snip/>


        public Customer find(string login) 
        {
            IList<Customer> customers;
            Object result = tt.Execute(delegate(ITransactionStatus status) //line 42
            {
                var transaction = status.Transaction;

                  var session = this.SessionFactory.GetCurrentSession();
                  //var transaction = session.BeginTransaction();
                  try
                  {
                      customers = session.CreateQuery("from Technolog.Rma.Business.Domain.Customer Customer where Customer.Login=?")
                          .SetParameter(0, login)
                          .List<Customer>();

                      if (customers.Count > 0)
                      {
                          return customers[0];
                      }
                  }
                  catch
                  {

                  }
                  finally
                  {
                      if (session != null) session.Close();
                  }

                  return null;
              });


            return (Customer)result;

        }

我现在遇到的错误是

Server Error in '/RMA' Application.
--------------------------------------------------------------------------------

Cannot access a disposed object.
Object name: 'AdoTransaction'. 
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'AdoTransaction'.

Source Error: 

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.  

Stack Trace: 


[ObjectDisposedException: Cannot access a disposed object.
Object name: 'AdoTransaction'.]
   NHibernate.Transaction.AdoTransaction.Commit() +425
   Spring.Data.NHibernate.HibernateTransactionManager.DoCommit(DefaultTransactionStatus status) in c:\_prj\spring-net\trunk\src\Spring\Spring.Data.NHibernate\Data\NHibernate\HibernateTransactionManager.cs:579
   Spring.Transaction.Support.AbstractPlatformTransactionManager.ProcessCommit(DefaultTransactionStatus status) in c:\_prj\spring-net\trunk\src\Spring\Spring.Data\Transaction\Support\AbstractPlatformTransactionManager.cs:853
   Spring.Transaction.Support.TransactionTemplate.Execute(TransactionDelegate transactionMethod) in c:\_prj\spring-net\trunk\src\Spring\Spring.Data\Transaction\Support\TransactionTemplate.cs:159
   Technolog.Rma.Business.Repositories.CustomerDAO.find(String login) in C:\work\samplemvc\src\Technolog.Rma.Business\Repositories\CustomerDAO.cs:42
   _dynamic_Technolog.Rma.Business.Repositories.CustomerDAO.find(Object , Object[] ) +147
   Spring.Reflection.Dynamic.SafeMethod.Invoke(Object target, Object[] arguments) in c:\_prj\spring-net\trunk\src\Spring\Spring.Core\Reflection\Dynamic\DynamicMethod.cs:156
   Spring.Aop.Framework.DynamicMethodInvocation.InvokeJoinpoint() in c:\_prj\spring-net\trunk\src\Spring\Spring.Aop\Aop\Framework\DynamicMethodInvocation.cs:100
   Spring.Dao.Support.PersistenceExceptionTranslationInterceptor.Invoke(IMethodInvocation invocation) in c:\_prj\spring-net\trunk\src\Spring\Spring.Data\Dao\Support\PersistenceExceptionTranslationInterceptor.cs:190
   CompositionAopProxy_33677284ca854c0b8c01a5b0ae0a0524.find(String login) +383
   Technolog.Rma.Web.Controllers.HomeController.Index(Int32 page) in C:\work\samplemvc\src\Technolog.Rma.Web\Controllers\HomeController.cs:36
   lambda_method(Closure , ControllerBase , Object[] ) +112
   System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +248
   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +39
   System.Web.Mvc.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12() +125
   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation) +640
   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +312
   System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +691
   System.Web.Mvc.Controller.ExecuteCore() +162
   System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +305
   System.Web.Mvc.<>c__DisplayClassb.<BeginProcessRequest>b__5() +62
   System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +20
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +469
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +375




--------------------------------------------------------------------------------
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.272 
2个回答

1
根据上面的评论,我按照实现osiv的指示进行了操作。我还发现我在本应该保持会话打开状态时关闭了它,从而导致了一个问题。
Cannot access a disposed object.

我使用OSIV的web.config文件是:

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=152368

  Spring.Context.Support.ContextHandler, Spring.Core

    <resource uri="~/Config/propertyConfigurer.xml" />
  -->
<configuration>
  <configSections>
    <sectionGroup name="spring">
      <section name="context" type="Spring.Context.Support.MvcContextHandler, Spring.Web.Mvc3" />
    </sectionGroup>
  </configSections>
  <appSettings>
    <add key="dataFile" value="App_Data\data.db3" />
    <add key="ClientValidationEnabled" value="true"/>
    <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
    <add key="Spring.Data.NHibernate.Support.OpenSessionInViewModule.SessionFactoryObjectName" value="SessionFactory"/>
  </appSettings>
  <spring>
    <context>
      <resource uri="file://~/Config/propertyConfigurer.xml" />
      <resource uri="file://~/Config/sessionFactory.xml" />
      <resource uri="file://~/Config/mappers.xml" />
      <resource uri="file://~/Config/repositories.xml" />
      <resource uri="file://~/Config/controllers.xml" />
      <resource uri="file://~/Config/scopedobjects.xml" />
      <resource uri="file://~/Config/utils.xml" />
    </context>
  </spring>
  <system.web>
    <httpModules>

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

    </httpModules>
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      </assemblies>
    </compilation>
    <pages>
      <namespaces>
        <add namespace="System.Web.Helpers" />
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
        <add namespace="System.Web.WebPages" />
      </namespaces>
    </pages>
    <authentication mode="Forms">
      <forms loginUrl="~/Account/LogOn" timeout="2880" />
    </authentication>
    <customErrors mode="Off"/>

  </system.web>
  <system.webServer>

    <validation validateIntegratedModeConfiguration="false" />
    <modules runAllManagedModulesForAllRequests="true">

      <add name="Spring" type="Spring.Context.Support.WebSupportModule, Spring.Web"/>
      <add name="OpenSessionInView" type="Spring.Data.NHibernate.Support.OpenSessionInViewModule, Spring.Data.NHibernate32"/>
    </modules>
    <!--
    <handlers>
      <add name="SpringPageHandler" verb="*" path="*.aspx" type="Spring.Web.Support.PageHandlerFactory, Spring.Web"/>
      <add name="SpringWebServiceHandler" verb="*" path="*.asmx" type="Spring.Web.Services.WebServiceHandlerFactory, Spring.Web" />
      <add name="SpringContextMonitor" verb="*" path="ContextMonitor.ashx" type="Spring.Web.Support.ContextMonitor, Spring.Web"/>
    </handlers>
    -->
  </system.webServer>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.7.0" newVersion="4.0.7.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

请注意,在我的开发环境中,osiv和spring WebSupportModule的引用是必须的,以使其正常工作,并且在IIS 7.5中使应用程序正常工作。
我还在我的视图中使用了延迟加载,因此osiv是更好的解决方案。我在问题中展示了编程事务控制,因为这是我尝试提出解决方案的进展。

+1 发布你的解决方案在这里;很高兴听到你已经让它工作了。 - Marijn

0

您已经配置了一个TransactionManager,但是您没有使用它。在调用SessionFactory.GetCurrentSession();之前,请尝试在您的事务管理器上启动一个事务。当使用Spring的事务管理时,您不应该显式地使用NHibernate的事务支持。

您可以通过编程方式声明方式来实现;在这个阶段,我建议您首先尝试编程方式。


你好Marijin,我已经进行了更改,以便通过编程方式应用交易,但是它们创建了不同的错误。我修改了我的原始帖子以展示我所做的更改和我得到的结果。明天我会声明性地执行交易并查看发生了什么。 - Abdul Jabbar Azam
让Spring为您处理会话管理,不要自己处理会话。 - Marijn
我根据Spring的OSIV文档 [链接](http://www.springframework.net/doc-latest/reference/html/orm.html#orm-hibernate-web)进行了一些更改,并发现在我的CustomerDAO.find方法中关闭了一个会话,这导致代码后面出现了异常。感谢Marijn的帮助。 - Abdul Jabbar Azam
太好了,你让它正常工作了!如果我没记错的话,在使用(编程或声明式)事务管理时,不需要osiv。但是我可能在这里弄错了。如果您将解决方案发布为答案,则可以接受它以让每个人都知道您的问题已解决-您可能还会得到一些赞 :) - Marijn
你好Marijn,你是对的,OSIV并不是必需的,但它可以让我的代码更简单。然而,如果需要更精细的事务控制,我可能会回归到编程控制。 - Abdul Jabbar Azam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接