C#と諸々

C#がメインで他もまぁ諸々なブログです
おかしなこと書いてたら指摘してくれると嬉しいです(´・∀・`)
つーかコメント欲しい(´・ω・`)

2006/10/08 04:29
業務エラーというのは、業務固有(アプリケーション固有)のエラーのこと。
例えば、DBに業務情報を格納しておくWebアプリで、あるユーザーが業務情報を登録しようとした時に、その業務情報に関連する情報が他のユーザーによって削除されていて、外部キー制約違反が起こってしまう場合などが該当する。


[ 業務エラーはApplicationExceptionで? ]

オレは今まで、業務エラー時にはApplicationException派生の自作クラスをスローしてた。
だって、ApplicationExceptionの説明には


ApplicationExceptionは、共通言語ランタイムではなく、ユーザー プログラムによってスローされます。デザインしているアプリケーションで固有の例外を作成する必要がある場合は、ApplicationException クラスの派生クラスを生成します。ApplicationException クラスは Exception を拡張しますが、新しい機能は追加しません。この例外は、アプリケーションで定義された例外とシステムで定義された例外を区別する手段として提供されます。


って書いてあるし、

Application Architecture for .NET ( 通称AAfN )第三章にも、


例外クラスは、ApplicationException の派生クラスとして作成します。


とか、


例外には大きく分けて、業務上の例外と技術上の例外の 2 種類があります。例外をこのように分類することにより、アプリケーションのさまざまなコンポーネントで該当する種類の例外をキャッチし、発行する処理を簡単に実現できるようになります。




  • 技術上の例外 (データベース接続の失敗など)

  • 業務上の例外 (外部キー制約の違反など)




って書いてあるから。(あとここにも。)



[ 業務エラーは戻り値で? ]
でも、クラス ライブラリ開発のデザイン ガイドラインの中のカスタム例外のデザインでは、


 「標準の例外の種類のキャッチとスロー」のガイドラインに示されているように、ApplicationException からカスタム例外を派生させることは推奨されていない点に注意します。

なんて書いてある。 ( 対象がクラス ライブラリ開発だからか・・・? )

書籍 「 Microsoft Visual Studio 2005 による Webアプリケーション構築技法 」 でも、 「 6.4 例外処理 」 で、DBに対して顧客情報を新規登録するメソッドを例に挙げ、終了パターンを以下のように3つに大別した上で、


・正常終了
受け渡された顧客情報を利用して、正常にデータベースに顧客情報が登録された場合。

・業務エラー
希望された顧客IDがすでに他の顧客により利用されていたといった理由により、顧客情報が登録できなかった場合。

・アプリケーション/システムエラー
データベース障害やネットワーク障害により、データベースの読み書きが行えなかった場合。


それぞれの表現方法を以下のように示している。 ( 実際は表形式 )


分類:
正常終了

対応するケース:
業務で期待された主たる処理が問題なく終了した場合

.NETでの表現方法:
戻り値の一部として表現


分類:
業務エラー

対応するケース:
業務設計の中で想定されている範囲内で、処理が分岐し、正常終了できなかった場合

.NETでの表現方法:
戻り値の一部として表現


分類:
アプリケーション/システムエラー

対応するケース:
業務設計の想定範囲外の異常事態が発生し、アプリケーション処理を正しく遂行できなくなった場合

.NETでの表現方法:
例外を用いて表現





[ ふむ・・・ ]
ということで、業務エラーについては、以下の2つの意見があるようだ。

・ApplicationExceptionの派生クラスを定義し、それをスローする。
・例外は用いず、戻り値 ( BooleanとかEnumってことかな ) で表す。

どっちがいいんだろ?
いや、単に人それぞれの好みで選んでいいのかな?
考察してみると面白そうだし、もしかしたらそのうち考察記事書くかも。
タグ: .NET C# 例外処理
2006/08/03 11:59
前に少し書いたが、ハンドルされなかった例外をGlobal.asaxのApplication_Errorでthis.Server.GetLastError()で取得すると、HttpUnhandledExceptionにラップされている。

しかし、ここで取得される例外が必ずHttpUnhandledExceptionという訳ではない。
というのも、アプリケーションではなくASP.NETが発生させた例外に対してはHttpUnhandledExceptionがスローされないからである。

例えば、Webフォームに対して危険な文字列を送信すると、HttpRequestValidationExceptionがASP.NETからスローされる。この例外はWebフォームのPage_Errorでハンドルすることができるのだが、ここでハンドルしなくてもHttpUnhandledExceptionはスローされない。

ASP.NETが発生させる例外は、全てHttpExceptionである。HttpRequestValidationExceptionはもちろんのこと、HttpUnhandledExceptionもHttpExceptionの派生クラスであり、ASP.NETが発生させる例外の一つである。
タグ: C# .NET ASP.NET 例外処理
2006/07/22 18:58
ASP.NETでは、ハンドルされなかった例外はGlobal.asaxのApplication_Error(HttpAplication.Errorイベントのハンドラ)で処理できる。
発生した例外は this.Server.GetLastError()で取得できるのだが、例外は基本的にHttpUnhandledExceptionにラップされている(必ずではない)ので注意する必要がある。
例外を処理したら this.Server.ClearError()でクリアすること。ただし、Web.configのcustomErrorsセクションに設定したエラー処理方法を適用させたい場合はクリアしない。

Global.asax void Application_Error(object sender, EventArgs e)
{
    Exception ex =
        this.Server.GetLastError() is HttpUnhandledException ?
        this.Server.GetLastError().InnerException :
        this.Server.GetLastError();
    this.Server.ClearError();
    if (ex is ApplicationException)
    {
        // 業務上の例外に対する処理
    }
    else
    {
        // 技術的な例外に対する処理
    }
}

また、ページ単位で例外ハンドラを用意することもできる。
この場合はPage_Error(TemplateControl.Errorイベントのハンドラ)で処理する。
Global.asaxのApplication_Errorとは違い、GetLastError()で取得できる例外はハンドルされなかった例外そのものである。

Hoge.aspx.cs protected void Page_Error(Object sender, EventArgs e)
{
    Exception ex = this.Server.GetLastError();
    this.Server.ClearError();
    if (ex is ApplicationException)
    {
        // 業務上の例外に対する処理
    }
    else
    {
        // 技術的な例外に対する処理
    }
}
タグ: C# .NET ASP.NET 例外処理