1

我将 NHibernate 与 Oracle 一起使用,我让 NHibernate 处理获取表主键的下一个序列值。在下面的代码中,我似乎无法让 NHibernate 在第二次调用 transaction.Commit() 时保存我的对象。数据库表 ReportSource 已经有一条记录,其中 Name 列设置为“test2”,并且我在 Name 列上设置了唯一约束。所以我希望第一个 transaction.Commit() 失败。但是,为什么在我使用当前不在数据库中的名称更新 ReportSource 对象后,第二个 transaction.Commit() 失败了?

        using (var session = Ioc.Container.Get<ISession>())
        {
            var db = new ReportSource { Name = "test2", ConnectionString = "test", Provider = "test" };
            using (var transaction = session.BeginTransaction())
            {
                try
                {
                    session.SaveOrUpdate(db);
                    transaction.Commit();
                }
                catch (Exception ex)
                {
                    transaction.Rollback();
                }
            }
            using (var transaction = session.BeginTransaction())
            {
                try
                {
                    db.Name = "test4";
                    //fails with or without the below statement
                    //session.SaveOrUpdate(db);
                    transaction.Commit();
                }
                catch (Exception ex)
                {
                    transaction.Rollback();
                }
            }
        }
4

1 回答 1

2

如果在数据库调用期间发生异常,则不应尝试在同一会话中执行任何其他操作。相反,应该丢弃当前会话,因为它不再处于一致状态。这就是 NHibernate 的文档所指出的

如果 ISession 抛出异常,您应该立即回滚事务,调用 ISession.Close() 并丢弃 ISession 实例。ISession 的某些方法不会使会话保持一致状态。

您应该创建另一个会话并重试,而不是尝试在同一个会话中进行另一个事务。

using (var session = Ioc.Container.Get<ISession>())
{
    var db = new ReportSource { 
        Name = "test2", ConnectionString = "test", Provider = "test" };
    using (var transaction = session.BeginTransaction())
    {
        try
        {
            session.SaveOrUpdate(db);
            transaction.Commit();
        }
        catch (Exception ex)
        {
            transaction.Rollback();
        }
    }
}
using (var session = Ioc.Container.Get<ISession>())
{
    using (var transaction = session.BeginTransaction())
    {
        try
        {
            // assign to the new session
            session.Update(db);
            db.Name = "test4";
            session.SaveOrUpdate(db);
            transaction.Commit();
        }
        catch (Exception ex)
        {
            transaction.Rollback();
        }
    }
}
于 2012-08-25T23:21:32.823 回答