Nhibernate 奇怪的错误

Nhibernate 奇怪的错误,nhibernate,session,transactions,Nhibernate,Session,Transactions,我看到一些奇怪的NHibernate错误偶尔出现在我们的生产环境中,但不是在我们的测试服务器上。几天过去了,没有错误,然后我们会收到一个错误,如下所示,就好像闸门已经打开,这些错误发生在我们网站的几十个不同部分。阻止它们发生的唯一方法是重置应用程序池 我们为传入的每个HTTP请求打开一个会话和伴随的事务。它存储在HttpContext.Current.Items集合中。我们的每个存储库都扩展了一个基本存储库类,该类引用以前打开的会话。以下是打开和关闭会话和事务的模块: public class

我看到一些奇怪的NHibernate错误偶尔出现在我们的生产环境中,但不是在我们的测试服务器上。几天过去了,没有错误,然后我们会收到一个错误,如下所示,就好像闸门已经打开,这些错误发生在我们网站的几十个不同部分。阻止它们发生的唯一方法是重置应用程序池

我们为传入的每个HTTP请求打开一个会话和伴随的事务。它存储在HttpContext.Current.Items集合中。我们的每个存储库都扩展了一个基本存储库类,该类引用以前打开的会话。以下是打开和关闭会话和事务的模块:

public class NHibernateSessionModule : IHttpModule
{
    #region Public Methods
    /// <summary>
    /// Initializes the http module by hooking up the open session call to the begin
    /// request event and the close session call to the end request event.
    /// </summary>
    /// <param name="context">The context representing the current http request.</param>
    public void Init(HttpApplication context)
    {
        context.BeginRequest += ApplicationBeginRequest;
        context.EndRequest += ApplicationEndRequest;
        context.Error += OnError;
    }

    /// <summary>
    /// Disposes of the module.
    /// </summary>
    public void Dispose() { }
    #endregion

    #region Private Methods
    /// <summary>
    /// Fired when an error occurs during a request. Cleans up any open sessions and transactions.
    /// </summary>
    /// <param name="sender">The sender of the event.</param>
    /// <param name="e">The event arguments.</param>
    private static void OnError(object sender, EventArgs e)
    {
        var system = HttpContext.Current.Items["SystemSession"] as Lazy<ISession>;
        if (system != null && system.IsValueCreated && system.Value != null)
            RollbackSession(system.Value);
    }

    /// <summary>
    /// Fired as a request begins. Opens a session and accompanying transaction. Also authenticates the
    /// currently logged in user.
    /// </summary>
    /// <param name="sender">The sender of the event.</param>
    /// <param name="e">The event arguments.</param>
    private static void ApplicationBeginRequest(object sender, EventArgs e)
    {
        OpenSession("SystemSession", SessionFactoryProvider.SystemSessionFactory);
            }

    /// <summary>
    /// Opens a new session.
    /// </summary>
    /// <param name="key">The key used to store the opened session in the current http context.</param>
    /// <param name="sessionFactory">The factory used to open the session.</param>
    private static void OpenSession(string key, ISessionFactory sessionFactory)
    {
        if (HttpContext.Current.Items[key] != null)
            return;

        HttpContext.Current.Items[key] = new Lazy<ISession>(() => {
            var session = sessionFactory.OpenSession();
            session.BeginTransaction();
            return session;
        }, true);
    }

    /// <summary>
    /// Fired as a request ends. Closes the previously opened session and commits the session's transaction.
    /// </summary>
    /// <param name="sender">The sender of the event.</param>
    /// <param name="e">The event arguments.</param>
    private static void ApplicationEndRequest(object sender, EventArgs e)
    {
        var system = HttpContext.Current.Items["SystemSession"] as Lazy<ISession>;
        if (system != null && system.IsValueCreated && system.Value != null)
            CommitSession(system.Value);
    }

    /// <summary>
    /// Commits a session's transaction.
    /// </summary>
    /// <param name="session">The session.</param>
    private static void CommitSession(ISession session)
    {
        if (session == null)
            return;

        if (session.Transaction != null && session.Transaction.IsActive)
        {
            var transaction = session.Transaction;
            try
            {
                transaction.Commit();
            }
            catch (Exception)
            {
                transaction.Rollback();
            }
        }
        session.Close();
    }

    /// <summary>
    /// Rolls back a session's transaction.
    /// </summary>
    /// <param name="session">The session.</param>
    private static void RollbackSession(ISession session)
    {
        if (session == null)
            return;

        if (session.Transaction != null && session.Transaction.IsActive)
            session.Transaction.Rollback();
        session.Close();
    }
    #endregion
}
上述许多错误都有内部异常消息,如:

System.InvalidOperationException: Invalid attempt to call Read when reader is closed.
System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.
System.Data.SqlClient.SqlException: New request is not allowed to start because it should come with valid transaction descriptor.
System.IndexOutOfRangeException: ID28_0_
NHibernate.AssertionFailure: possible non-threadsafe access to the session
System.InvalidOperationException: ExecuteReader requires an open and available Connection. The connection's current state is open.
很多这样的错误看起来好像一个会话正在跨多个线程打开、访问或关闭,但我们不会产生任何其他线程来访问应用程序中任何位置的数据库

通过查看NHibernate探查器的日志,我们知道在任何情况下都会打开和提交/回滚事务

我们试图解决这个问题已经有一段时间了,但已经没有办法了。以前有人遇到过这个问题吗?有什么想法吗

谢谢

Chris

我们没有使用NHibernate,所以我不确定这是否适用,但我们每天都会收到大量的GetOrdinal错误。DataReader和datatables返回了意外数据(即,来自与我们预期完全不同的查询)。我最近发现了“登记”连接字符串参数,在向所有连接字符串添加了“登记=False”之后,我们没有抛出一个GetOrdinal错误

我相信这一改变可能会解决人们在这里和其他地方报道的许多类似问题


Mike

您可能应该重新抛出捕获的异常,而不是尝试回滚并忽略它……嗨,Chris,我们在nHibernate中看到了类似的奇怪行为。事情间歇性地工作,然后我们会得到类似于您报告的错误。你解决过这个问题吗?谢谢
public class BaseRepository<T>
{
    #region Properties
    /// <summary>
    /// Opens and returns a new session.
    /// </summary>
    private static ISession OpenSession
    {
        get
        {
            if (HttpContext.Current != null)
            {
                var lazySession = (Lazy<ISession>)HttpContext.Current.Items["SystemSession"];
                if (lazySession != null)
                    return lazySession.Value;
            }
            TypeContainer.Get<ILog>().Warn("Unable to find session in http context");

            throw new InvalidOperationException("The current HTTP context contains no system session.");
        }
    }

    private ISession _session;
    public ISession CurrentSession
    {
        get
        {
            if (_session == null || !_session.IsOpen || _session.Connection.State == ConnectionState.Closed)
                _session = OpenSession;
            return _session;
        }
    }
    #endregion
}
CustomerID20_
at System.Data.ProviderBase.FieldNameLookup.GetOrdinal(String fieldName) 
at System.Data.SqlClient.SqlDataReader.GetOrdinal(String name) 
at NHibernate.Driver.NHybridDataReader.GetOrdinal(String name) 
at NHibernate.Type.NullableType.NullSafeGet(IDataReader rs, String name) 
at NHibernate.Type.NullableType.NullSafeGet(IDataReader rs, String[] names, ISessionImplementor session, Object owner) 
at NHibernate.Loader.Loader.GetKeyFromResultSet(Int32 i, IEntityPersister persister, Object id, IDataReader rs, ISessionImplementor session) 
at NHibernate.Loader.Loader.GetRowFromResultSet(IDataReader resultSet, ISessionImplementor session, QueryParameters queryParameters, LockMode[] lockModeArray, EntityKey optionalObjectKey, IList hydratedObjects, EntityKey[] keys, Boolean returnProxies) 
at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) 
at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) 
at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters)

The server failed to resume the transaction. Desc:480000000f.
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) 
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) 
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() 
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) 
at System.Data.SqlClient.SqlDataReader.ConsumeMetaData() 
at System.Data.SqlClient.SqlDataReader.get_MetaData() 
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) 
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) 
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) 
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) 
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) 
at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) 
at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader() 
at NHibernate.AdoNet.AbstractBatcher.ExecuteReader(IDbCommand cmd) 
at NHibernate.Loader.Loader.GetResultSet(IDbCommand st, Boolean autoDiscoverTypes, Boolean callable, RowSelection selection, ISessionImplementor session) 
at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) 
at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) 
at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters)

CustomerID26_
at System.Data.ProviderBase.FieldNameLookup.GetOrdinal(String fieldName) 
at System.Data.SqlClient.SqlDataReader.GetOrdinal(String name) 
at NHibernate.Driver.NHybridDataReader.GetOrdinal(String name) 
at NHibernate.Type.NullableType.NullSafeGet(IDataReader rs, String name) 
at NHibernate.Type.NullableType.NullSafeGet(IDataReader rs, String[] names, ISessionImplementor session, Object owner) 
at NHibernate.Type.ManyToOneType.Hydrate(IDataReader rs, String[] names, ISessionImplementor session, Object owner) 
at NHibernate.Type.ComponentType.Hydrate(IDataReader rs, String[] names, ISessionImplementor session, Object owner) 
at NHibernate.Type.ComponentType.NullSafeGet(IDataReader rs, String[] names, ISessionImplementor session, Object owner) 
at NHibernate.Loader.Loader.GetKeyFromResultSet(Int32 i, IEntityPersister persister, Object id, IDataReader rs, ISessionImplementor session) 
at NHibernate.Loader.Loader.GetRowFromResultSet(IDataReader resultSet, ISessionImplementor session, QueryParameters queryParameters, LockMode[] lockModeArray, EntityKey optionalObjectKey, IList hydratedObjects, EntityKey[] keys, Boolean returnProxies) 
at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) 
at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) 
at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters)

Transaction not connected, or was disconnected
at NHibernate.Transaction.AdoTransaction.CheckNotZombied() 
at NHibernate.Transaction.AdoTransaction.Rollback() 
at ACC.Web.Modules.NHibernateSessionModule.CommitSession(ISession session) 
at ACC.Web.Modules.NHibernateSessionModule.ApplicationEndRequest(Object sender, EventArgs e) 
at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() 
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

ID28_0_
at System.Data.ProviderBase.FieldNameLookup.GetOrdinal(String fieldName) 
at System.Data.SqlClient.SqlDataReader.GetOrdinal(String name) 
at NHibernate.Driver.NHybridDataReader.GetOrdinal(String name) 
at NHibernate.Type.NullableType.NullSafeGet(IDataReader rs, String name) 
at NHibernate.Type.NullableType.NullSafeGet(IDataReader rs, String[] names, ISessionImplementor session, Object owner) 
at NHibernate.Loader.Loader.GetKeyFromResultSet(Int32 i, IEntityPersister persister, Object id, IDataReader rs, ISessionImplementor session) 
at NHibernate.Loader.Loader.GetRowFromResultSet(IDataReader resultSet, ISessionImplementor session, QueryParameters queryParameters, LockMode[] lockModeArray, EntityKey optionalObjectKey, IList hydratedObjects, EntityKey[] keys, Boolean returnProxies) 
at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) 
at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) 
at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters)

Transaction not successfully started
at NHibernate.Transaction.AdoTransaction.CheckBegun() 
at NHibernate.Transaction.AdoTransaction.Rollback() 
at ACC.Web.Modules.NHibernateSessionModule.CommitSession(ISession session) 
at ACC.Web.Modules.NHibernateSessionModule.ApplicationEndRequest(Object sender, EventArgs e) 
at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() 
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

col_0_0_
at System.Data.ProviderBase.FieldNameLookup.GetOrdinal(String fieldName) 
at System.Data.SqlClient.SqlDataReader.GetOrdinal(String name) 
at NHibernate.Driver.NHybridDataReader.GetOrdinal(String name) 
at NHibernate.Type.NullableType.NullSafeGet(IDataReader rs, String name) 
at NHibernate.Type.NullableType.NullSafeGet(IDataReader rs, String[] names, ISessionImplementor session, Object owner) 
at NHibernate.Hql.Ast.ANTLR.Loader.QueryLoader.GetResultColumnOrRow(Object[] row, IResultTransformer resultTransformer, IDataReader rs, ISessionImplementor session) 
at NHibernate.Loader.Loader.GetRowFromResultSet(IDataReader resultSet, ISessionImplementor session, QueryParameters queryParameters, LockMode[] lockModeArray, EntityKey optionalObjectKey, IList hydratedObjects, EntityKey[] keys, Boolean returnProxies) 
at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) 
at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) 
at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters)

The server failed to resume the transaction. Desc:8040000001d.
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) 
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) 
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() 
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) 
at System.Data.SqlClient.SqlDataReader.ConsumeMetaData() 
at System.Data.SqlClient.SqlDataReader.get_MetaData() 
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) 
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) 
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) 
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) 
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) 
at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) 
at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader() 
at NHibernate.AdoNet.AbstractBatcher.ExecuteReader(IDbCommand cmd) 
at NHibernate.Loader.Loader.GetResultSet(IDbCommand st, Boolean autoDiscoverTypes, Boolean callable, RowSelection selection, ISessionImplementor session) 
at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) 
System.InvalidOperationException: Invalid attempt to call Read when reader is closed.
System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.
System.Data.SqlClient.SqlException: New request is not allowed to start because it should come with valid transaction descriptor.
System.IndexOutOfRangeException: ID28_0_
NHibernate.AssertionFailure: possible non-threadsafe access to the session
System.InvalidOperationException: ExecuteReader requires an open and available Connection. The connection's current state is open.