1

私はOracleでNHibernateを使用しており、NHibernateにテーブルの主キーの次のシーケンス値の取得を処理させています。以下のコードでは、2 回目の transaction.Commit() の呼び出しで NHibernate にオブジェクトを保存させることができないようです。データベース テーブル ReportSource には、Name 列が "test2" に設定されたレコードが既にあり、Name 列に一意の制約が設定されています。したがって、最初の transaction.Commit() が失敗することを期待しています。しかし、現在データベースにない名前で ReportSource オブジェクトを更新した後、2 番目の 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 に答える