NHibernate并发更新问题

时间:2018-11-29 13:02:19

标签: c# nhibernate

我目前正在测试c#/ NHibernate应用程序的并发更新情况。 在休眠配置中,command_timeout被设置为1秒用于测试目的。 我在映射文件中使用了休眠version

以下是测试代码:

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            MyHibernateConnector hc = new MyHibernateConnector(); // 1 usage see below; also provides some other hibernate related methods
            MyHibernateConfig myhibconfig = new MyHibernateConfig(); // reads and holds hibernate configuration
            hc.setHibernateConfig(myhibconfig);

            ISession session = hc.getSessionAndStartTransaction();
            // getSessionAndStartTransaction() does the following:
            // - on first call: reads the hibernate configuration and builds the SessionFactory
            // - gets the session as follows:
            //   ISession session;
            //   if (CurrentSessionContext.HasBind(sf))
            //   {
            //       session = sf.GetCurrentSession();
            //   }
            //   else
            //   {
            //       session = sf.OpenSession();
            //       CurrentSessionContext.Bind(session);
            //   }
            // - and does session.BeginTransaction();

            MyClass obj;
            IQuery q = session.CreateQuery("select mc from MyClass as mc where mc.ID = ?");
            q.SetInt64(0, 60);

            l = q.List<MyClass>();
            if (l.Count > 0)
                obj = l[0];

            session.Transaction.Rollback();

            // now update obj in another application with autocommit off and do not commit or rollback

/* breakpont is set here */            session = hc.getSessionAndStartTransaction();

            try
            {
                session.Lock(obj, LockMode.Upgrade);
            } catch (Exception e)
            {
                try
                {
                    session.Transaction.Rollback();
                }
                catch (Exception e2)
                {
                    Type t = e2.GetType();
                }
            }
            // ...
        }
    }
}

session.Lock(obj, LockMode.Upgrade)上,异常(GenericADOException)与消息一起抛出:

could not lock: … for update

如果我现在捕获此异常并尝试执行ISession.Transaction.Rollback(),则会抛出TransactionException

我希望回滚是解决并发更新情况的适当措施。不是吗?适当的行动是什么? TransactionException之后事务的状态是什么?

我使用NHibernate 5.1.0.0版和MySql.Data 6.10.7.0版。休眠属性dialectNHibernate.Dialect.MySQL55InnoDBDialect

1 个答案:

答案 0 :(得分:0)

经过更多的实验之后,我认为我找到了解决方案-或者我应该说一个解决方法: ISession.Connection发生超时后,session.Lock(obj, LockMode.Upgrade)关闭,因此在回滚之前再次将其打开:

if (session.Connection.State.Equals(ConnectionState.Closed)) // <- !!!
    session.Connection.Open();
session.Transaction.Rollback();

这有效,我可以在同一会话中进行进一步的交易。

为什么首先关闭连接对我来说还是个谜!

我想知道这种行为是否对其他(所有?)底层DBMS和/或驱动程序通用。