1

私はMVCEF5セットアップを持っており、クラスは次のとおりです。

  • Program-これはコントローラーです
  • UserInterface-これはビューであり、データの表示とプロンプトを表示します。
  • DataAccess-モデル、これは私のEFモデルクラスのデータを作成、読み取り、更新、および削除します

DataAccessクラスがデータベースでCRUD操作を実行しようとしたときに、エラーが発生した場合はそれを処理する必要があります。UserInterfaceクラスはユーザーにメッセージを出力し、必要に応じてエラーを報告する必要があります。したがって、エラーが発生した場合、データ層はプレゼンテーション層と直接通信するべきではないため、最初にプログラムクラスを通過し、次にUserInterfaceクラスを通過する必要があります。

呼び出し元の関数に例外を渡したり返したりしないことを提案されましたが、「上のレイヤーに新しい単純な例外をスローする」必要があります。例外に関する私の経験は次の形式に限定されているため、例外に関するこのすべての話は私を混乱させます。

try
{
    // stuff
}
catch (exception ex)
{
    console.writeline(ex.ToString());
}

私はこの問題の答えを見つけるために自分自身の調査をいくつか行いました。いくつかのことを学びましたが、すべてをまとめる方法がわかりません。

私は学んだ:

  • throw;例外を再スローし、スタックトレースを保持します
  • throw exキャッチブロックでキャッチされたものなど、既存の例外をスローします。スタックトレースをリセットします。
  • Exception.StackTraceというプロパティがあります。例外がスローされるたびに、呼び出しスタックのフレームがException.StackTraceプロパティに記録されることを理解しています。

ただし、再スローを利用するためにtry/catchブロックをどこに配置するかわかりません

次のコードのようなものですか?それとも、これがどのように機能するかについてのポイントを逃していますか?

編集:(他の人にこの当て推量を理解するためにもう少し追加)

        void MethodA()  
        {
            try
            {
                MethodB();
            }
            catch (MyExceptionType ex)
            {
                // Do stuff appropriate for MyExceptionType
                throw;
            }
        }
        void MethodB()  
        {
            try
            {
                MethodC();
            }
            catch (AnotherExceptionType ex)
            {
                // Do stuff appropriate for AnotherExceptionType
                throw;
            }
        }
        void MethodC()  
        {
            try
            {
                // Do Stuff
            }
            catch (YetAnotherExceptionType ex)
            {
                // Do stuff appropriate for YetAnotherExceptionType
                throw;
            }
        }
4

2 に答える 2

2

さまざまなタイプの例外処理を使用する方法以上のものがあります。機能的には、例外を除いて、どのレイヤーが何をしなければならないかを定義する必要があります。

データレイヤーのように=>DataExceptionまたはSQLException以外のものをスローしないでください。それらをログに記録し、一般的なデータベース例外をUIにスローバックします。

ビジネスレイヤー=>単純なビジネス例外をログに記録して再スローするUIレイヤー=>ビジネス例外のみをキャッチし、ビジネス例外内のメッセージでアラートを出す

これがすべて定義されたら、問題で学習および要約した内容を使用して、これを構築できます。

于 2012-12-27T19:30:46.380 に答える
2

新しいより単純な例外をスローすることによって(私が思うに)提案されたことは、下位層からの例外を、外部層で消費するための新しい、より高いレベルの例外に変換することです。下位レベルの例外は、プログラムの上位レベルでの消費には適していません。

たとえば、LINQ to Entitiesでは、シーケンスに要素がない場合、メソッドSingle()はをスローします。InvalidOperationExceptionただし、この例外タイプは非常に一般的であるため、ユーザーインターフェイスレベルでキャッチするのは困難です。この例外がスローされる可能性をどのように区別しますか(たとえば、読み取り専用コレクションの変更)。解決策は、例外を、アプリケーションが簡単に処理できる別の(新しいユーザー定義の)タイプに変換することです。

アイデアの簡単な例を次に示します。

public class MyUserService {
    public User GetById(int id) {
        try {
            using(var ctx = new ModelContainer()) {
                return ctx.Where(u => u.Id == id).Single();
            }
        }
        catch(InvalidOperationException) {
            // OOPs, there is no user with the given id!
            throw new UserNotFoundException(id);
        }
    }
}

次に、ProgramレイヤーはUserNotFoundExceptionをキャッチし、何が起こったかを即座に知ることができるため、ユーザーにエラーを説明するための最良の方法を見つけることができます。詳細はプログラムの正確な構造によって異なりますが、ASP.NETMVCアプリでは次のように機能します。

public class MyUserController : Controller {
    private MyUserService Service = new MyUserService();
    public ActionResult Details(int id) {
        User user;
        try {
            user = Service.GetById(id);
        }
        catch(UserNotFoundException) {
            // Oops, there is no such user. Return a 404 error
            // Note that we do not care about the InvalidOperationException
            // that was thrown inside GetById
            return HttpNotFound("The user does not exist!");
        }
        // If we reach here we have a valid user
        return View(user);
     }
}
于 2012-12-27T19:49:56.320 に答える