NHibernate Transaction.Commit()

发布于 2024-12-11 04:44:14 字数 14791 浏览 0 评论 0原文

我有一个大问题,它涉及 NHibernate 中的事务。

首先,我可以说 SessionManager(线程安全、惰性单例)创建一个 SessionFactory 并为我提供会话对象。事务管理是内置的。

接下来,我有一个带有 hibernate 映射(xml,无流利)和 poco 的 DAL。

WCF 服务正在免费提供一些 poco,这通过以下方式发生:

    public string UpdateCustomer(Customer customer, ExtraParameters extraParameters)
    {
        try
        {
            using (_daof.BeginTransaction(GetInstanceUserID(extraParameters)))
            {
                return _daof.GetKlantDao().UpdateCustomer(customer).SekKlant.ToString();
            }
        }
        catch (Exception ex)
        {
            ServiceExceptionHandling(ex);
        }
        return null;
    }

如您所见, using 语句处理事务和会话的处置:

  public CrmDaoFactory BeginTransaction(string userID)
    {
        CrmSettings.Instance.UserID = userID; //Not important
        SessionManager.Instance.BeginTransactionOn(configKey); //Memory leak
        return this;
    }

处置是通过处置模式(析构函数)完成的:

     protected virtual void Dispose(bool disposing)
    {
        if (disposing == true)
        {
            if (Marshal.GetExceptionCode() == 0)
            {
                SessionManager.Instance.CommitTransactionOn(configKey);
            }
            else
            {
                SessionManager.Instance.RollbackTransactionOn(configKey);
            }

            SessionManager.Instance.CloseSessionOn(configKey);
        }
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

       ~CrmDaoFactory() { Dispose(false); }

在上面,您可以看到当调用 dispose 时,事务被提交(也刷新会话),当发生错误时,事务被回滚。最后,我关闭会话。

问题是当我调用服务上的方法时,我注意到内存泄漏。当我引用 BeginTransaction 行时,没有发生内存泄漏。

    public CrmDaoFactory BeginTransaction(string userID)
    {
        CrmSettings.Instance.UserID = userID;
        //SessionManager.Instance.BeginTransactionOn(configKey);
        return this;
    }

当我调试代码时,我非常确定所有会话在处理后都已关闭。 为了供您参考,我使用以下“SessionManager”代码:

 using System;
using System.Collections;
using System.IO;
using System.Runtime.Remoting.Messaging;
using System.Web;
using System.Web.Caching;

using NHibernate;
using NHibernate.Cache;
using System.Reflection;

namespace Cevi.Hibernate
{
    /// <summary>
    /// Handles creation and management of sessions and transactions.  It is a singleton because 
    /// building the initial session factory is very expensive. Inspiration for this class came 
    /// from Chapter 8 of Hibernate in Action by Bauer and King.  Although it is a sealed singleton
    /// you can use TypeMock (http://www.typemock.com) for more flexible testing.
    /// </summary>
    public sealed class SessionManager
    {
        //private static readonly DataInterceptor _dataInterceptor = new DataInterceptor();

        #region Thread-safe, lazy Singleton

        /// <summary>
        /// This is a thread-safe, lazy singleton.  See http://www.yoda.arachsys.com/csharp/singleton.html
        /// for more details about its implementation.
        /// </summary>
    public static SessionManager Instance
    {
        get
        {
            return Nested.SessionManager;
        }
    }

    /// <summary>
    /// Private constructor to enforce singleton
    /// </summary>
    private SessionManager() {  }

    /// <summary>
    /// Assists with ensuring thread-safe, lazy singleton
    /// </summary>
    private class Nested
    {
        static Nested() {  }
        internal static readonly SessionManager SessionManager = new SessionManager();
    }

    #endregion

    /*
    /// <summary>
    /// This method attempts to find a session factory in the <see cref="HttpRuntime.Cache" /> 
    /// via its config file path; if it can't be found it creates a new session factory and adds
    /// it the cache.  Note that even though this uses HttpRuntime.Cache, it should still work in 
    /// Windows applications; see http://www.codeproject.com/csharp/cacheinwinformapps.asp for an
    /// examination of this.
    /// </summary>
    /// <param name="sessionFactoryConfigPath">Path location of the factory config</param>
    private ISessionFactory GetSessionFactoryFor(string sessionFactoryConfigPath)
    {
        if (string.IsNullOrEmpty(sessionFactoryConfigPath))
            throw new ArgumentNullException("sessionFactoryConfigPath may not be null nor empty");

        //  Attempt to retrieve a cached SessionFactory from the HttpRuntime's cache.
        ISessionFactory sessionFactory = (ISessionFactory)HttpRuntime.Cache.Get(sessionFactoryConfigPath);

        //  Failed to find a cached SessionFactory so make a new one.
        if (sessionFactory == null)
        {
            if (!File.Exists(sessionFactoryConfigPath))
                // It would be more appropriate to throw a more specific exception than ApplicationException
                throw new ApplicationException(
                    "The config file at '" + sessionFactoryConfigPath + "' could not be found");

            NHibernate.Cfg.Configuration cfg = new NHibernate.Cfg.Configuration();
            cfg.Configure(sessionFactoryConfigPath);

            //  Now that we have our Configuration object, create a new SessionFactory
            sessionFactory = cfg.BuildSessionFactory();

            if (sessionFactory == null)
            {
                throw new InvalidOperationException("cfg.BuildSessionFactory() returned null.");
        }

            HttpRuntime.Cache.Add(sessionFactoryConfigPath, sessionFactory, null, DateTime.Now.AddDays(7),
                TimeSpan.Zero, CacheItemPriority.High, null);
        }

        return sessionFactory;
    }
    */

    /// <summary>
    /// This method attempts to find a session factory in the <see cref="HttpRuntime.Cache" /> 
    /// via its config file path; if it can't be found it creates a new session factory and adds
    /// it the cache.  Note that even though this uses HttpRuntime.Cache, it should still work in 
    /// Windows applications; see http://www.codeproject.com/csharp/cacheinwinformapps.asp for an
    /// examination of this.
    /// </summary>
    /// <param name="sessionFactoryConfigPath">Path location of the factory config</param>
    public ISessionFactory GetSessionFactoryFor(string sessionFactoryConfigPath)
    {
        if (string.IsNullOrEmpty(sessionFactoryConfigPath))
            throw new ArgumentNullException("sessionFactoryConfigPath may not be null nor empty");

        // Attempt to retrieve a cached SessionFactory from the HttpRuntime's cache.
        ISessionFactory sessionFactory = (ISessionFactory)HttpRuntime.Cache.Get(sessionFactoryConfigPath);

        // Failed to find a cached SessionFactory so make a new one.
        if (sessionFactory == null)
        {
            string path = sessionFactoryConfigPath;
            if (!Path.IsPathRooted(path))
            // indien het geen absoluut pad is afhankelijk van de context waarin de hibernate laag gebruikt wordt het path anders aanvullen
            {
                if (HttpContext.Current != null)
                    path = HttpContext.Current.Server.MapPath("~/" + path);
                else if (!string.IsNullOrEmpty(System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath))
                    path = Path.Combine(System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath, path);
                else
                {
                    string assemblyPath = (Assembly.GetEntryAssembly()!=null)?  
                        Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) : 
                        AppDomain.CurrentDomain.BaseDirectory;
                    if (!string.IsNullOrEmpty(assemblyPath))
                        path = Path.Combine(assemblyPath, path);
                }
            }

            if (!File.Exists(path))
                // It would be more appropriate to throw a more specific exception than ApplicationException
                throw new ApplicationException(
                "The config file at '" + sessionFactoryConfigPath + "' could not be found");

            NHibernate.Cfg.Configuration cfg = new NHibernate.Cfg.Configuration();
            cfg.Configure(path);
            //cfg.SetInterceptor(new DataInterceptor());

            // Now that we have our Configuration object, create a new SessionFactory
            sessionFactory = cfg.BuildSessionFactory();

            if (sessionFactory == null)
            {
                throw new InvalidOperationException("cfg.BuildSessionFactory() returned null.");
            }

            HttpRuntime.Cache.Add(sessionFactoryConfigPath, sessionFactory, null, DateTime.Now.AddDays(7),
            TimeSpan.Zero, CacheItemPriority.High, null);
        }
        return sessionFactory;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="sessionFactoryConfigPath"></param>
    /// <param name="interceptor"></param>
    public void RegisterInterceptorOn(string sessionFactoryConfigPath, IInterceptor interceptor)
    {
        ISession session = (ISession)ContextSessions[sessionFactoryConfigPath];

        if (session != null && session.IsOpen)
        {
            throw new CacheException("You cannot register an interceptor once a session has already been opened");
        }

        GetSessionFrom(sessionFactoryConfigPath, interceptor);
    }

    /// <summary>
    /// </summary>
    /// <param name="sessionFactoryConfigPath"></param>
    /// <returns></returns>
    public ISession GetSessionFrom(string sessionFactoryConfigPath)
    {
        return GetSessionFrom(sessionFactoryConfigPath, null);
    }

    private ISession GetSessionFrom(string sessionFactoryConfigPath, IInterceptor interceptor)
    {
        ISession session = (ISession)ContextSessions[sessionFactoryConfigPath];

        if (session == null)
        {
            session = (interceptor != null)? 
                GetSessionFactoryFor(sessionFactoryConfigPath).OpenSession(interceptor) : 
                GetSessionFactoryFor(sessionFactoryConfigPath).OpenSession();

            ContextSessions[sessionFactoryConfigPath] = session;
        }

        if (session == null)
            // It would be more appropriate to throw a more specific exception than ApplicationException
            throw new ApplicationException("session was null");

        return session;
    }

    ///<summary>
    ///</summary>
    ///<param name="sessionFactoryConfigPath"></param>
    public void CloseSessionOn(string sessionFactoryConfigPath)
    {
        ISession session = (ISession)ContextSessions[sessionFactoryConfigPath];
        if (session != null && session.IsOpen)
        {
            session.Close();
            session.Dispose();
        }
        ContextSessions.Remove(sessionFactoryConfigPath);


    }

    ///<summary>
    ///</summary>
    ///<param name="sessionFactoryConfigPath"></param>
    public void BeginTransactionOn(string sessionFactoryConfigPath)
    {
        ITransaction transaction = (ITransaction)ContextTransactions[sessionFactoryConfigPath];

        if (transaction == null)
        {
            transaction = GetSessionFrom(sessionFactoryConfigPath).BeginTransaction();
            ContextTransactions.Add(sessionFactoryConfigPath, transaction);
        }
    }

    ///<summary>
    ///</summary>
    ///<param name="sessionFactoryConfigPath"></param>
    public void CommitTransactionOn(string sessionFactoryConfigPath)
    {
        ITransaction transaction = (ITransaction)ContextTransactions[sessionFactoryConfigPath];

        try
        {
            if (transaction != null && !transaction.WasCommitted && !transaction.WasRolledBack)
            {
                transaction.Commit();
                ContextTransactions.Remove(sessionFactoryConfigPath);
                transaction.Dispose();
            }
        }
        catch (HibernateException)
        {
            RollbackTransactionOn(sessionFactoryConfigPath);
            throw;
        }
    }

    ///<summary>
    ///</summary>
    ///<param name="sessionFactoryConfigPath"></param>
    public void RollbackTransactionOn(string sessionFactoryConfigPath)
    {
        ITransaction transaction = (ITransaction)ContextTransactions[sessionFactoryConfigPath];

        try
        {
            ContextTransactions.Remove(sessionFactoryConfigPath);

            if (transaction != null && !transaction.WasCommitted && !transaction.WasRolledBack)
            {
                transaction.Rollback();
            }
        }
        finally
        {
            CloseSessionOn(sessionFactoryConfigPath);
        }
    }

    /// <summary>
    /// Since multiple databases may be in use, there may be one transaction per database 
    /// persisted at any one time.  The easiest way to store them is via a hashtable
    /// with the key being tied to session factory.
    /// </summary>
    private static Hashtable ContextTransactions
    {
        get
        {
            if (CallContext.GetData("CONTEXT_TRANSACTIONS") == null)
            {
                CallContext.SetData("CONTEXT_TRANSACTIONS", new Hashtable());
        }

            return (Hashtable)CallContext.GetData("CONTEXT_TRANSACTIONS");
        }
    }

    /// <summary>
    /// Since multiple databases may be in use, there may be one session per database 
    /// persisted at any one time.  The easiest way to store them is via a hashtable
    /// with the key being tied to session factory.
    /// </summary>
    private static Hashtable ContextSessions
    {
        get
        {
            if (CallContext.GetData("CONTEXT_SESSIONS") == null)
            {
                CallContext.SetData("CONTEXT_SESSIONS", new Hashtable());
        }
            return (Hashtable)CallContext.GetData("CONTEXT_SESSIONS");
        }
    }

    /// <summary>
    /// Opens a stateless session 
    /// </summary>
    /// <param name="sessionFactoryConfigPath"></param>
    /// <returns></returns>
    public IStatelessSession StatelessSession(string sessionFactoryConfigPath)
    {
        return GetSessionFactoryFor(sessionFactoryConfigPath).OpenStatelessSession();
    }
}
}

有人能给我一些线索吗?我已经没有主意了。 哦,二级缓存和查询缓存被禁用:

<property name="cache.use_second_level_cache">false</property>
<property name="cache.use_query_cache">false</property>

谢谢

I have a big problem and it concernes transactions in NHibernate.

To kick off I can say that a SessionManager (thread-safe, lazy Singleton) creates a SessionFactory and gives me session objects. Transaction Management is build in.

Next, I have a DAL with hibernate mappings (xml, no fluent) and poco's.

A WCF service is giving some poco's free and that happens via this way:

    public string UpdateCustomer(Customer customer, ExtraParameters extraParameters)
    {
        try
        {
            using (_daof.BeginTransaction(GetInstanceUserID(extraParameters)))
            {
                return _daof.GetKlantDao().UpdateCustomer(customer).SekKlant.ToString();
            }
        }
        catch (Exception ex)
        {
            ServiceExceptionHandling(ex);
        }
        return null;
    }

As you can see, the using statement handles the transaction and the disposing of the session:

  public CrmDaoFactory BeginTransaction(string userID)
    {
        CrmSettings.Instance.UserID = userID; //Not important
        SessionManager.Instance.BeginTransactionOn(configKey); //Memory leak
        return this;
    }

Disposing is done via the Disposing Pattern (destructor):

     protected virtual void Dispose(bool disposing)
    {
        if (disposing == true)
        {
            if (Marshal.GetExceptionCode() == 0)
            {
                SessionManager.Instance.CommitTransactionOn(configKey);
            }
            else
            {
                SessionManager.Instance.RollbackTransactionOn(configKey);
            }

            SessionManager.Instance.CloseSessionOn(configKey);
        }
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

       ~CrmDaoFactory() { Dispose(false); }

Above, you can see that when dispose is called, the transaction is commited (flushes also the session) and when an error occured it's rollbacked. Finally, I close the session.

The problem is when I call methods on the service, I notice a memory leak. When I quote the BeginTransaction line, no memory leak occurs.

    public CrmDaoFactory BeginTransaction(string userID)
    {
        CrmSettings.Instance.UserID = userID;
        //SessionManager.Instance.BeginTransactionOn(configKey);
        return this;
    }

I'm quite sure all the sessions are closed after the disposal, as I debugged the code.
For your info, I use the following 'SessionManager' code:

 using System;
using System.Collections;
using System.IO;
using System.Runtime.Remoting.Messaging;
using System.Web;
using System.Web.Caching;

using NHibernate;
using NHibernate.Cache;
using System.Reflection;

namespace Cevi.Hibernate
{
    /// <summary>
    /// Handles creation and management of sessions and transactions.  It is a singleton because 
    /// building the initial session factory is very expensive. Inspiration for this class came 
    /// from Chapter 8 of Hibernate in Action by Bauer and King.  Although it is a sealed singleton
    /// you can use TypeMock (http://www.typemock.com) for more flexible testing.
    /// </summary>
    public sealed class SessionManager
    {
        //private static readonly DataInterceptor _dataInterceptor = new DataInterceptor();

        #region Thread-safe, lazy Singleton

        /// <summary>
        /// This is a thread-safe, lazy singleton.  See http://www.yoda.arachsys.com/csharp/singleton.html
        /// for more details about its implementation.
        /// </summary>
    public static SessionManager Instance
    {
        get
        {
            return Nested.SessionManager;
        }
    }

    /// <summary>
    /// Private constructor to enforce singleton
    /// </summary>
    private SessionManager() {  }

    /// <summary>
    /// Assists with ensuring thread-safe, lazy singleton
    /// </summary>
    private class Nested
    {
        static Nested() {  }
        internal static readonly SessionManager SessionManager = new SessionManager();
    }

    #endregion

    /*
    /// <summary>
    /// This method attempts to find a session factory in the <see cref="HttpRuntime.Cache" /> 
    /// via its config file path; if it can't be found it creates a new session factory and adds
    /// it the cache.  Note that even though this uses HttpRuntime.Cache, it should still work in 
    /// Windows applications; see http://www.codeproject.com/csharp/cacheinwinformapps.asp for an
    /// examination of this.
    /// </summary>
    /// <param name="sessionFactoryConfigPath">Path location of the factory config</param>
    private ISessionFactory GetSessionFactoryFor(string sessionFactoryConfigPath)
    {
        if (string.IsNullOrEmpty(sessionFactoryConfigPath))
            throw new ArgumentNullException("sessionFactoryConfigPath may not be null nor empty");

        //  Attempt to retrieve a cached SessionFactory from the HttpRuntime's cache.
        ISessionFactory sessionFactory = (ISessionFactory)HttpRuntime.Cache.Get(sessionFactoryConfigPath);

        //  Failed to find a cached SessionFactory so make a new one.
        if (sessionFactory == null)
        {
            if (!File.Exists(sessionFactoryConfigPath))
                // It would be more appropriate to throw a more specific exception than ApplicationException
                throw new ApplicationException(
                    "The config file at '" + sessionFactoryConfigPath + "' could not be found");

            NHibernate.Cfg.Configuration cfg = new NHibernate.Cfg.Configuration();
            cfg.Configure(sessionFactoryConfigPath);

            //  Now that we have our Configuration object, create a new SessionFactory
            sessionFactory = cfg.BuildSessionFactory();

            if (sessionFactory == null)
            {
                throw new InvalidOperationException("cfg.BuildSessionFactory() returned null.");
        }

            HttpRuntime.Cache.Add(sessionFactoryConfigPath, sessionFactory, null, DateTime.Now.AddDays(7),
                TimeSpan.Zero, CacheItemPriority.High, null);
        }

        return sessionFactory;
    }
    */

    /// <summary>
    /// This method attempts to find a session factory in the <see cref="HttpRuntime.Cache" /> 
    /// via its config file path; if it can't be found it creates a new session factory and adds
    /// it the cache.  Note that even though this uses HttpRuntime.Cache, it should still work in 
    /// Windows applications; see http://www.codeproject.com/csharp/cacheinwinformapps.asp for an
    /// examination of this.
    /// </summary>
    /// <param name="sessionFactoryConfigPath">Path location of the factory config</param>
    public ISessionFactory GetSessionFactoryFor(string sessionFactoryConfigPath)
    {
        if (string.IsNullOrEmpty(sessionFactoryConfigPath))
            throw new ArgumentNullException("sessionFactoryConfigPath may not be null nor empty");

        // Attempt to retrieve a cached SessionFactory from the HttpRuntime's cache.
        ISessionFactory sessionFactory = (ISessionFactory)HttpRuntime.Cache.Get(sessionFactoryConfigPath);

        // Failed to find a cached SessionFactory so make a new one.
        if (sessionFactory == null)
        {
            string path = sessionFactoryConfigPath;
            if (!Path.IsPathRooted(path))
            // indien het geen absoluut pad is afhankelijk van de context waarin de hibernate laag gebruikt wordt het path anders aanvullen
            {
                if (HttpContext.Current != null)
                    path = HttpContext.Current.Server.MapPath("~/" + path);
                else if (!string.IsNullOrEmpty(System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath))
                    path = Path.Combine(System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath, path);
                else
                {
                    string assemblyPath = (Assembly.GetEntryAssembly()!=null)?  
                        Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) : 
                        AppDomain.CurrentDomain.BaseDirectory;
                    if (!string.IsNullOrEmpty(assemblyPath))
                        path = Path.Combine(assemblyPath, path);
                }
            }

            if (!File.Exists(path))
                // It would be more appropriate to throw a more specific exception than ApplicationException
                throw new ApplicationException(
                "The config file at '" + sessionFactoryConfigPath + "' could not be found");

            NHibernate.Cfg.Configuration cfg = new NHibernate.Cfg.Configuration();
            cfg.Configure(path);
            //cfg.SetInterceptor(new DataInterceptor());

            // Now that we have our Configuration object, create a new SessionFactory
            sessionFactory = cfg.BuildSessionFactory();

            if (sessionFactory == null)
            {
                throw new InvalidOperationException("cfg.BuildSessionFactory() returned null.");
            }

            HttpRuntime.Cache.Add(sessionFactoryConfigPath, sessionFactory, null, DateTime.Now.AddDays(7),
            TimeSpan.Zero, CacheItemPriority.High, null);
        }
        return sessionFactory;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="sessionFactoryConfigPath"></param>
    /// <param name="interceptor"></param>
    public void RegisterInterceptorOn(string sessionFactoryConfigPath, IInterceptor interceptor)
    {
        ISession session = (ISession)ContextSessions[sessionFactoryConfigPath];

        if (session != null && session.IsOpen)
        {
            throw new CacheException("You cannot register an interceptor once a session has already been opened");
        }

        GetSessionFrom(sessionFactoryConfigPath, interceptor);
    }

    /// <summary>
    /// </summary>
    /// <param name="sessionFactoryConfigPath"></param>
    /// <returns></returns>
    public ISession GetSessionFrom(string sessionFactoryConfigPath)
    {
        return GetSessionFrom(sessionFactoryConfigPath, null);
    }

    private ISession GetSessionFrom(string sessionFactoryConfigPath, IInterceptor interceptor)
    {
        ISession session = (ISession)ContextSessions[sessionFactoryConfigPath];

        if (session == null)
        {
            session = (interceptor != null)? 
                GetSessionFactoryFor(sessionFactoryConfigPath).OpenSession(interceptor) : 
                GetSessionFactoryFor(sessionFactoryConfigPath).OpenSession();

            ContextSessions[sessionFactoryConfigPath] = session;
        }

        if (session == null)
            // It would be more appropriate to throw a more specific exception than ApplicationException
            throw new ApplicationException("session was null");

        return session;
    }

    ///<summary>
    ///</summary>
    ///<param name="sessionFactoryConfigPath"></param>
    public void CloseSessionOn(string sessionFactoryConfigPath)
    {
        ISession session = (ISession)ContextSessions[sessionFactoryConfigPath];
        if (session != null && session.IsOpen)
        {
            session.Close();
            session.Dispose();
        }
        ContextSessions.Remove(sessionFactoryConfigPath);


    }

    ///<summary>
    ///</summary>
    ///<param name="sessionFactoryConfigPath"></param>
    public void BeginTransactionOn(string sessionFactoryConfigPath)
    {
        ITransaction transaction = (ITransaction)ContextTransactions[sessionFactoryConfigPath];

        if (transaction == null)
        {
            transaction = GetSessionFrom(sessionFactoryConfigPath).BeginTransaction();
            ContextTransactions.Add(sessionFactoryConfigPath, transaction);
        }
    }

    ///<summary>
    ///</summary>
    ///<param name="sessionFactoryConfigPath"></param>
    public void CommitTransactionOn(string sessionFactoryConfigPath)
    {
        ITransaction transaction = (ITransaction)ContextTransactions[sessionFactoryConfigPath];

        try
        {
            if (transaction != null && !transaction.WasCommitted && !transaction.WasRolledBack)
            {
                transaction.Commit();
                ContextTransactions.Remove(sessionFactoryConfigPath);
                transaction.Dispose();
            }
        }
        catch (HibernateException)
        {
            RollbackTransactionOn(sessionFactoryConfigPath);
            throw;
        }
    }

    ///<summary>
    ///</summary>
    ///<param name="sessionFactoryConfigPath"></param>
    public void RollbackTransactionOn(string sessionFactoryConfigPath)
    {
        ITransaction transaction = (ITransaction)ContextTransactions[sessionFactoryConfigPath];

        try
        {
            ContextTransactions.Remove(sessionFactoryConfigPath);

            if (transaction != null && !transaction.WasCommitted && !transaction.WasRolledBack)
            {
                transaction.Rollback();
            }
        }
        finally
        {
            CloseSessionOn(sessionFactoryConfigPath);
        }
    }

    /// <summary>
    /// Since multiple databases may be in use, there may be one transaction per database 
    /// persisted at any one time.  The easiest way to store them is via a hashtable
    /// with the key being tied to session factory.
    /// </summary>
    private static Hashtable ContextTransactions
    {
        get
        {
            if (CallContext.GetData("CONTEXT_TRANSACTIONS") == null)
            {
                CallContext.SetData("CONTEXT_TRANSACTIONS", new Hashtable());
        }

            return (Hashtable)CallContext.GetData("CONTEXT_TRANSACTIONS");
        }
    }

    /// <summary>
    /// Since multiple databases may be in use, there may be one session per database 
    /// persisted at any one time.  The easiest way to store them is via a hashtable
    /// with the key being tied to session factory.
    /// </summary>
    private static Hashtable ContextSessions
    {
        get
        {
            if (CallContext.GetData("CONTEXT_SESSIONS") == null)
            {
                CallContext.SetData("CONTEXT_SESSIONS", new Hashtable());
        }
            return (Hashtable)CallContext.GetData("CONTEXT_SESSIONS");
        }
    }

    /// <summary>
    /// Opens a stateless session 
    /// </summary>
    /// <param name="sessionFactoryConfigPath"></param>
    /// <returns></returns>
    public IStatelessSession StatelessSession(string sessionFactoryConfigPath)
    {
        return GetSessionFactoryFor(sessionFactoryConfigPath).OpenStatelessSession();
    }
}
}

Can someone give me some clue what's going on? I'm running out of ideas.
Oh, second level cache and query cache are disabled:

<property name="cache.use_second_level_cache">false</property>
<property name="cache.use_query_cache">false</property>

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文