6

NHibernate で例外を処理するためのベスト プラクティスは何ですか?

次の SubjectRepository があります。

    public void Add(Subject subject)
    {
        using (ISession session = HibernateUtil.CurrentSession)
        using (ITransaction transaction = session.BeginTransaction())
        {

            session.Save(subject);
            transaction.Commit();
        }
    }

そして、ユニットテストは次のとおりです。

        [Test]
    public void TestSaveDuplicate()
    {
        var subject = new Subject
        {
            Code = "En",
            Name = "English"
        };

        _subjectRepository.Add(subject);

        var duplicateSubject = new Subject
        {
            Code = "En",
            Name = "English1"
        };

        _subjectRepository.Add(duplicateSubject);
    }

単体テストで生成されたエラーを処理するところまで来て、少し行き詰まりました。これは期待どおりに失敗しますが、GenericADOException の場合、ConstraintViolationException または同様のものを期待していました (データベース レベルでサブジェクト コードに一意性制約があります)。

ADOException は、適切なエラー メッセージを持つ MySQL 例外をラップしますが、内部例外をスローするだけでカプセル化を破ることはしたくありません。特に、MySQL はこのプロジェクトのバックエンドとして確定していません。

理想的には、例外をキャッチして、この時点で適切なエラーをユーザーに返すことができるようにしたいと考えています。NHibernate Exceptions を処理し、何が問題で、その理由をユーザーに報告するための文書化されたベスト プラクティス アプローチはありますか?

ありがとう、

マット

4

4 に答える 4

13

Add メソッドで次のように処理します。

public void Add(Subject subject)
{
    using (ISession session = HibernateUtil.CurrentSession)
    using (ITransaction transaction = session.BeginTransaction())
    {
        try
        {
            session.Save(subject);
            transaction.Commit();
        }
        catch (Exception ex)
        {
            transaction.Rollback();
            // log exception
            throw;
        }
    }
}

catch ブロックでは、最初にトランザクションをロールバックし、例外をログに記録する必要があります。次に、オプションは次のとおりです。

  1. 同じ例外を再スローします。これは私のバージョンが行うことです
  2. 独自の例外でラップし、それをスローします
  3. 何もせずに例外を飲み込みます。これが良い考えであることはめったにありません

このメソッドで例外を処理するための実際のオプションはありません。UI がこのメソッドを呼び出すと仮定すると、独自の try..catch でそれを呼び出し、意味のあるエラー メッセージをユーザーに表示して処理する必要があります。ExpectedException(type) 属性を使用して、単体テストに合格することができます。

質問に直接答えるには、Exception を拡張して独自の「賢明なエラー」を作成し、元の例外を InnerException としてスローする必要があります。これが、(2) でリストした例外ラッピング手法です。

于 2009-04-09T23:52:21.990 に答える
2

すべての Nhibernate 例外は回復できません。nhibernate 例外から回復しようとしている場合は、アプリ/データ層の設計を再検討することができます。また、spring.net の例外変換実装もご覧ください 。また、例外でトランザクションを手動で処理するのは面倒でエラーが発生しやすいので、nhibernate の contextual sessionsをご覧ください。Spring.net には、 nhibernate に関する優れたヘルパーもあります。

于 2009-04-10T00:12:34.500 に答える
1

一般的な質問は、ユーザーに何を伝えたいのか、ユーザーは誰なのかということです。

ユーザーが時々別のコンピュータになる場合 (つまり、これが Web サービスの場合) は、適切なメカニズムを使用して SOAP エラーまたは HTTP エラーを返します。

ユーザーがある種の UI になることがある場合、ユーザーにメッセージを表示したい場合がありますが、ユーザーがそれについて何かできるようにするには、何を伝えますか? たとえば、ほとんどの Web サイトでは、理由が何であれ、「申し訳ありませんが、予期しないエラーが発生しました」と表示されます。これは、通常、ユーザーがエラーに対してできることは何もないためです。

ただし、どちらの場合でも、「ユーザー」に伝える方法の選択は、DAL ではなく、プレゼンテーション層 (UI 層) の問題です。DAL からの例外を別の例外タイプでラップする必要がある可能性がありますが、メッセージを変更する場合に限ります。独自の例外クラスは必要ありませんが、それが他の種類ではなくデータ アクセス例外である場合に、呼び出し元が別のことを行う場合を除きます。

于 2009-04-09T23:29:38.223 に答える