Nhibernate查询很容易失败

Nhibernate查询很容易失败,nhibernate,Nhibernate,我真的很难解决一个来自NHibernate(3.3)的问题。该应用程序在六节点NLB集群中提供大约150个请求/秒。应用程序通常运行正常,但有时可能在1-2天内日志中出现以下错误,所有查询都失败 我使用的是adonet.batch\u size为15,并且MultipleActiveResultSets=True设置为True。所有控制器都继承自AsyncController(这是一个ASP.NET MVC 4应用程序),因此会话状态为只读,以最大限度地提高并发性 最初,我们在NHibernat

我真的很难解决一个来自NHibernate(3.3)的问题。该应用程序在六节点NLB集群中提供大约150个请求/秒。应用程序通常运行正常,但有时可能在1-2天内日志中出现以下错误,所有查询都失败

我使用的是
adonet.batch\u size
为15,并且
MultipleActiveResultSets=True
设置为True。所有控制器都继承自
AsyncController
(这是一个ASP.NET MVC 4应用程序),因此会话状态为只读,以最大限度地提高并发性

最初,我们在NHibernate会话处理方面遇到了很多问题,因为
AbstractBatcher
在管理与哪个连接相关的读卡器方面做得很差。因此,在高负载情况下,读卡器会尝试读取已经关闭的连接。我们通过手动定义SQLConnection的生存期来解决这个问题,SQLConnection可以稳定事物

然而,以下情况经常出现。我认为这是会话工厂出了问题的征兆。此时,我正在考虑在抛出这种类型的未处理异常时重新初始化会话工厂,但这并不好。有人知道为什么会这样吗

System.NotSupportedException: PartialEvaluationExceptionExpression
   at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitExpression(Expression expression)
   at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitBinaryExpression(BinaryExpression expression)
   at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitExpression(Expression expression)
   at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitBinaryExpression(BinaryExpression expression)
   at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitExpression(Expression expression)
   at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitBinaryExpression(BinaryExpression expression)
   at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitExpression(Expression expression)
   at NHibernate.Linq.Visitors.QueryModelVisitor.VisitWhereClause(WhereClause whereClause, QueryModel queryModel, Int32 index)
   at Remotion.Linq.Clauses.WhereClause.Accept(IQueryModelVisitor visitor, QueryModel queryModel, Int32 index)
   at Remotion.Linq.QueryModelVisitorBase.VisitBodyClauses(ObservableCollection`1 bodyClauses, QueryModel queryModel)
   at Remotion.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel queryModel)
   at NHibernate.Linq.Visitors.QueryModelVisitor.GenerateHqlQuery(QueryModel queryModel, VisitorParameters parameters, Boolean root)
   at NHibernate.Linq.NhLinqExpression.Translate(ISessionFactoryImplementor sessionFactory)
   at NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(String queryIdentifier, IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary`2 filters, ISessionFactoryImplementor factory)
   at NHibernate.Engine.Query.QueryPlanCache.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow, IDictionary`2 enabledFilters)
   at NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow)
   at NHibernate.Impl.AbstractSessionImpl.CreateQuery(IQueryExpression queryExpression)
   at NHibernate.Linq.DefaultQueryProvider.PrepareQuery(Expression expression, IQuery& query, NhLinqExpression& nhQuery)
   at NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression)
   at NHibernate.Linq.DefaultQueryProvider.Execute[TResult](Expression expression)
   at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source)

对于那些可能面临这个问题的人,我想我会给出一些关于我们为解决这个问题而实施的修复程序的两年(数千名用户)的见解

在基本构造函数中,我们有如下内容:

        public MvcBaseController()
        {
            try
            {
                var currentRepositorySession = RepositorySession.Current;

                dbConnection = new SqlConnection(currentRepositorySession.GetConnectionString());
                dbConnection.Open();
                session = currentRepositorySession.Create(false, dbConnection);

            }
            catch (Exception e)
            {
                LogDebug("Error was thrown: " + e.Message);
            }
        }
将db连接强制绑定到NHibernate会话是确保
AbstractBatcher
不会在完成所有读卡器之前关闭会话的唯一方法。在
Dispose
上,我们有以下内容:

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            try
            {
                if (session != null)
                {
                    session.Dispose();
                    session = null;
                }
            }
            catch (Exception ex)
            {
                LogDebug("Error was thrown: " + ex.Message);
            }
            try
            {
                if (dbConnection != null)
                {
                    dbConnection.Close();
                    dbConnection.Dispose();
                    dbConnection = null;
                }
            }
            catch (Exception ex)
            {
                LogDebug("Error was thrown: " + ex.Message);
            }
        }

        base.Dispose(disposing);
    }
这意味着为每个请求打开一个连接,这很好。我们不得不增加SQL Server工作人员,但该系统已经稳定两年了。我们唯一一次看到NHibernate会话工厂中断是当有大量数据从数据库中分页时,比如说一百万条记录。然后,应用程序池溢出,成为孤立池。这些主要是代码错误,与问题中描述的并发性问题无关