3

初めてモデルを挿入しようとしたときにデータベースからエラーが返された後、モデルを挿入できないのはなぜですか。

Report report = null;
using (var session = SessionFactory.OpenSession()) {
    try {
        using (var transaction = session.BeginTransaction()) {
            report = new Report();
            session.SaveOrUpdate(report);//Exception: Name field required
            transaction.Commit();
        }
    }
    catch { }

    try {
        using (var transaction = session.BeginTransaction()) {
            report.Name = "theName";
            session.SaveOrUpdate(report);

            //Causes Exception:
            //Row was updated or deleted by another transaction (or unsaved-value 
            //mapping was incorrect): [ReportViewer.DataAccess.Models.Report#22]                          
            transaction.Commit();
        }
    }
    catch { }
}

しかし、既存のモデルを更新しているときにエラーが発生した場合は、修正を行い (この場合は名前を設定)、更新を再試行することができます。

Report report = null;
using (var session = SessionFactory.OpenSession()) {
    using (var transaction = session.BeginTransaction()) {
        report = new Report();
        report.Name = "theName";
        session.SaveOrUpdate(report);
        transaction.Commit();
    }
}
using (var session = SessionFactory.OpenSession()) {

    //get entity saved from previous session
    report = session.Get<Report>(report.Id);

    try {
        using (var transaction = session.BeginTransaction()) {
            report.Name = null;
            session.SaveOrUpdate(report);//Exception: Name field required
            transaction.Commit();
        }
    }
    catch { }

    try {
        using (var transaction = session.BeginTransaction()) {

            //updates and does not give an error
            report.Name = "theName";
            session.SaveOrUpdate(report);
            transaction.Commit();
        }
    }
    catch { }
}
4

2 に答える 2

4

データベースによってトリガーされた例外が発生した場合、NHibernate セッションを閉じる (破棄する)必要があります。例外の後、(内部的に、または DB 状態と) 一貫性があることは保証されません。

NHibernate リファレンス の例外処理に関する章を参照してください。

于 2013-02-17T19:34:07.723 に答える
2

Oskar が言ったように、例外が発生した後は NHibernate セッションを破棄する必要があります。ただし、挿入が失敗する理由は、レポートを呼び出しSaveOrUpdateて永続化しているためです (ここで使用する必要がありSaveます)。同じインスタンスで再度呼び出すとSaveOrUpdate、NHibernate は例外をスローします。これは、オブジェクトが既に永続化されているためです。次のようにコードを書き直すと、挿入が成功する可能性があります (ただし、お勧めしません)。

try {
    using (var transaction = session.BeginTransaction()) {
        report.Name = "theName";                   
        transaction.Commit();
    }
}

update の例でSaveOrUpdateは、NHibernate がオブジェクトをロードしたときにオブジェクトが永続化されたため、呼び出しは効果がありません。NHibernate のインスタンスの状態と永続オブジェクトの操作方法を理解することは基本的なことであり、広く誤解されています。

はるかに優れた方法は、オブジェクトをデータベースに保存する前に検証することです。

于 2013-02-18T15:00:48.443 に答える