2

サービスレイヤーに次のコードがあり、EFを使用してデータベースに新しいユーザーを追加します。

    public User AddUser(User user)
    {
        using (var context = DataObjectFactory.CreateContext())
        {
            var userEntity = Mapper.Map(user);

            context.AddObject("UserEntities", userEntity);

            context.SaveChanges();

            return Mapper.Map(userEntity);
        }         
    }

そして、これは次のメソッドを介してサービスレイヤーによって呼び出されます。

    public UserResponse GetSubmitUser(UserRequest request)
    {
        var response = new UserResponse(request.RequestId);

        var user = Mapper.FromDataTransferObject(request.User);

        response.User = Mapper.ToDataTransferObject(UserDao.AddUser(user));

        return response;
    }

AddUserに到達する前に、特定のクライアントとサーバーの検証を行いますが、未処理の例外を処理する方法がわかりません。

たとえば、context.SaveChanges()がエラーをスローした場合、エラーの詳細をプレゼンテーション層に戻すにはどうすればよいですか?

私は次のようにAddUser内にtry/catchを配置することを考えています:

    public User AddUser(User user)
    {
        try
        {
            using (var context = DataObjectFactory.CreateContext())
            {
                var userEntity = Mapper.Map(user);

                context.AddObject("UserEntities", userEntity);

                context.SaveChanges();

                return Mapper.Map(userEntity);
            }  
        }
        catch (Exception)
        {
            return ??
        }      
    }

しかし、AddUserの戻りタイプはUserであり、例外が発生したときに何を返す必要があるのか​​わかりません。例外の詳細をUserResponseメソッドに返すことができれば、エラーの詳細を保持するためにそこにある応答オブジェクト内のいくつかのフィールドにデータを入力できますが、catchセクション内から何を返すかを確認してください。

データアクセス層、サービス層、プレゼンテーション層などの多層アプリケーションでキャッチして処理する必要のある例外を特定する方法を理解しようとしています。主に、例外の詳細をユーザーに表示する方法を理解しようとしています。解像度。

ありがとう

4

4 に答える 4

2

「BusinessExceptions」はあなたが探しているものだと思います。

n層アプリケーションでは、サービス層からビジネスルールの例外を取得または作成する際に問題が発生することがよくあります。例を使用していくつかのビジネスルールを検証しようとしていると思います。ユーザー名が有効であるか、DBにまだ存在していない可能性があります。

この種の問題については、私は常にFaultExceptionsとカスタムオブジェクトを使用して、クライアント側に「理解できる」メッセージを送信します。このようにして、システム例外、バグ例外、およびビジネスルール例外(ユーザーが知りたいもの)を区別できます。

これは私が通常行う方法です。壊れたビジネスルールのデータを含むBusinessFaultオブジェクトがあります。このデータはクライアントによって処理され、必要に応じてユーザーに表示されます。

[DataContract]
public class BusinessFault
{
    [DataMember]
    public BusinessFaultType Type { get; set; }

    [DataMember]
    public string Details { get; set; }

    [DataMember]
    public ErrorCode ErrorCode { get; set; }

    public BusinessFault(BusinessFaultType type, ErrorCode errorCode)
    {
        Type = type;
        ErrorCode = errorCode;
    }

    public BusinessFault(BusinessFaultType type, string details, ErrorCode errorCode)
        : this(type, errorCode)
    {
        Details = details;
    }

}

したがって、ルールを確認する必要があるときはいつでも、次のように使用します(例を使用)。

public void AddUser(User user)
{
if(!IsValidUser(user))
 throw new FaultException<BusinessFault>(new BusinessFault(BusinessFaultType.Validation, "Username",ErrorCode.AlreadyExists); 

using (var context = DataObjectFactory.CreateContext())
    {
        var userEntity = Mapper.Map(user);

        context.AddObject("UserEntities", userEntity);

        context.SaveChanges();

        return Mapper.Map(userEntity);
    } 
}

私のサービス契約では、BusinessFaultを既知のタイプとして指定する必要があります。このようにして、この障害はクライアント側に到達します。

    [OperationContract]
    [FaultContract(typeof(BusinessFault))]
    void AddUser(User user);                              

したがって、クライアント側で必要なのは、BusinessFaultに固有のtry-catchだけです。

try
{
    //WebService call
}
catch (FaultException<BusinessFault> ex)
{
var exception = ex.ToBusinessExeption();  //I use extensions Methods to convert it in a custom Exception with the parameters I sent. 
            throw exception;
}     

これについては非常に良い記事があります:http ://www.c-sharpcorner.com/UploadFile/afenster/wcf-error-handling-and-faultexceptions/

于 2012-10-04T16:20:30.823 に答える
1

あなたがそれで何かをするつもりであるならば、あなたはあなたのより低い層で例外を捕まえる必要があるだけです。たとえば、それをキャッチし、例外ログに書き込んでから、再スローすることができます。

戻り値に関しては、私の意見では、複数の場所から戻ってくるべきではありません。

むしろ、これはより良いと思います:

User user = null;

try
{
   //Try to set up user
}
catch(Exception ex)
{
   //Log exception
   throw;
}

return user;
于 2012-10-04T16:02:54.547 に答える
1

しかし、AddUserの戻りタイプはUserであり、例外が発生したときに何を返す必要があるのか​​わかりません

それは状況によって異なります-通常、値を返したくないのですが、例外をログに記録してから呼び出しthrow;(または、元の例外をラップする独自の例外をスローし、選択したもの)、例外をバブルアップします。どこかでそれをキャッチし、ユーザーに素敵なメッセージを表示して、ログに記録します。

ユーザーに素敵なメッセージを表示したい場合(および/または上位レベルのどこかでロギングを実行したい場合)、throw new ApplicationException("Failed to create user", ex);この方法を使用して素敵なメッセージを取得し、スタックトレースで例外をバブルして、後で問題を理解して修正できるようにします。

場合によっては、nullを返し、例外をログに記録することができます。通常、これは、例外をバブルしたくない場合、重要ではない場合、それが原因で現在のコードパスを終了したくない場合に行います。

幸運を!

于 2012-10-04T16:03:38.197 に答える
1

データアクセス層で例外をキャッチする必要はありません。自然にスローさせます。ルールは、ビジネスプロセスを実行する必要がある場合に例外をキャッチすることです。そうでない場合は、そのままにします。

したがって、トラブルシューティングのためにログに記録するために、すべての例外がアプリケーションの最上位層でキャッチされます。

アプリケーションがWebの場合、 Elmahなどのログハンドラーをサポートするログライブラリを使用して、リクエストレベルでインターセプトできます。

于 2012-10-04T16:06:02.150 に答える