NHibernate赢得';如果我的对象是以前失败的事务的一部分,请不要保存它

NHibernate赢得';如果我的对象是以前失败的事务的一部分,请不要保存它,nhibernate,transactions,oracle11g,Nhibernate,Transactions,Oracle11g,我将NHibernate与Oracle一起使用,并让NHibernate处理获取表主键的下一个序列值。在下面的代码中,我似乎无法让NHibernate在第二次调用transaction.Commit()时保存我的对象。数据库表ReportSource已经有一个记录,其名称列设置为“test2”,并且我在名称列上设置了唯一的约束。因此,我预计第一个事务.Commit()会失败。但是为什么在我用数据库中当前不存在的名称更新ReportSource对象之后,第二个transaction.Commit(

我将NHibernate与Oracle一起使用,并让NHibernate处理获取表主键的下一个序列值。在下面的代码中,我似乎无法让NHibernate在第二次调用transaction.Commit()时保存我的对象。数据库表ReportSource已经有一个记录,其名称列设置为“test2”,并且我在名称列上设置了唯一的约束。因此,我预计第一个事务.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();
                }
            }
        }
使用(var session=Ioc.Container.Get())
{
var db=new ReportSource{Name=“test2”,ConnectionString=“test”,Provider=“test”};
使用(var transaction=session.BeginTransaction())
{
尝试
{
session.SaveOrUpdate(db);
Commit();
}
捕获(例外情况除外)
{
transaction.Rollback();
}
}
使用(var transaction=session.BeginTransaction())
{
尝试
{
db.Name=“test4”;
//有或没有以下语句时失败
//session.SaveOrUpdate(db);
Commit();
}
捕获(例外情况除外)
{
transaction.Rollback();
}
}
}

如果在数据库调用期间发生异常,则不应尝试在同一会话中执行任何其他操作。相反,应该丢弃当前会话,因为它不再处于一致状态。这就是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();
        }
    }
}
使用(var session=Ioc.Container.Get())
{
var db=新的报告源{
Name=“test2”,ConnectionString=“test”,Provider=“test”};
使用(var transaction=session.BeginTransaction())
{
尝试
{
session.SaveOrUpdate(db);
Commit();
}
捕获(例外情况除外)
{
transaction.Rollback();
}
}
}
使用(var session=Ioc.Container.Get())
{
使用(var transaction=session.BeginTransaction())
{
尝试
{
//分配给新会话
更新(db);
db.Name=“test4”;
session.SaveOrUpdate(db);
Commit();
}
捕获(例外情况除外)
{
transaction.Rollback();
}
}
}