2016-08-27 17 views
0

データベースでレコードが見つからない場合に、どのような方法が好ましいかわかりません。 nullを返すFindメソッドやRecordNotFoundExceptionを返すGetメソッドを記述する方が良いですか?Return(RecordNotFound)レコードがデータベースに見つからない場合は、例外またはnull?

[AuthenticateFilter(UsernameAndSecretKey)] 
[Route("api/v1/activities/emails/{id}")] 
[HttpGet] 
public IHttpActionResult GetEmailActivity(int id) 
{ 
    try 
    { 
    // business logic service, could use only db service but this way we can do unit tests (just fill bl service method with fake objects) 
    var service = new EmailActivityBlService(); 

    // 1. use Find method which returns null in case record with provided id does not exist in db 
    var model = service.FindActivity(id); 
    if(model != null) 
     return Ok(model); 
    return NotFound(); 

    // 2. or is this approach better 
    // throws RecordNotFoundException in case row by id is not found in database 
    return Ok(service.GetActivity(id)); 
    } 
    catch(RecordNotFoundException e) { return NotFound(); } 
    catch(Exception e) { return InternalServerError(e); } 
} 

EmailActivityBlServiceは(唯一の重要な部分を示す)興味がある場合、誰に次のコードを持っている:私の同僚と話し

private EmailActivityDbService _dbService; 

public EmailActivityModel GetActivity(int id) 
{ 
    var model = this._dbService.GetActivity(id); 
    if(model == null) 
    throw new RecordNotFoundException(); // I suppose System.Data.ObjectNotFound is also suitable 
    return model; 
} 

public EmailActivityModel FindActivity(int id) 
{ 
    // typical entity framework query 
    // using(var context = new ..) { return contect.EmailActivity.Where()..SingleOrDefault().ConvertToModel(); 
    return this._dbService.GetActivity(id); 
} 

UPDATE

、我々は、このソリューションで行くことにしました。 GetActivityではなく、例外を投げるのnullを返す理由として、私はrboeから答えを好む:それはあなたのドメインで発生する可能性がある場合

だからレコードが存在しないことを、nullを返します(私の経験では、これはほとんどの場合あり場合)。レコードが存在すると予想され、レコードが存在しない場合は、例外をスローすることが有効です。

[AuthenticateFilter(UsernameAndSecretKey)] 
[Route("api/v1/activities/emails/{id}")] 
[HttpGet] 
public IHttpActionResult GetEmailActivity(int id) 
{ 
    var service = new EmailActivityBlService(); 
    var model = service.GetActivity(id); // returns null in case activity is not found 
    if(model != null) 
    return Ok(model); 
    return NotFound(); 
} 

我々は、メソッド内の任意のtry-catchを回避し、例外が発生したときにグローバルフィルタを置く:

ファイル:App_Start \ WebApiConfig.cs

public class WebApiExceptionFilter : ExceptionFilterAttribute 
{ 
    public override void OnException(HttpActionExecutedContext actionExecutedContext) 
    { 
    actionExecutedContext.Response = actionExecutedContext.Request.CreateErrorResponse(HttpStatusCode.InternalServerError, actionExecutedContext.Exception.Message, actionExecutedContext.Exception); 
    } 
} 

答えて

1

どちらの方法が有効であるともの。

例外または戻り値nullを使用するかどうかは、既存のレコードが存在しないことを示すために重要な意味を持ちません。

エラー状態(何か異常が発生したこと)を通知するための例外が存在します。 catchハンドラのコードは、エラーを処理する方法とビジネスロジックを含まない方法に焦点を当てています。

nullを返すと、モデルでは正常で「例外的」な状態になります。

あなたのドメインで起こる可能性がある場合は、nullを返します。そのレコードは存在しません(これは私の経験ではたいていの場合です)。レコードが存在すると予想され、レコードが存在しない場合は、exceptionをスローすることが有効です。

+0

ご意見ありがとうございます。 –

1

私は他の答えには同意しません。 GetyByIdメソッドの場合、要求されたIDを持つレコードが存在しない可能性があると「期待している」と主張できるので、スローする代わりにnullを返すとは言いません。この「例外的な状況の例外」は、しばしば述べられていますが、私はこのメソッドの契約について考える最善の方法ではないと思います。 APIは理想的には意味的な意味を持つはずです。

代わりに、メソッドが実行するよう指示されたときに例外をスローするように指示します。そのため、GetByIdメソッドは、システム内で要求されたIDを持つレコードが存在しない場合に例外をスローする必要があります。 Findメソッドはおそらく列挙型を返すべきですが、与えられた条件に一致するレコードがない場合はもちろん、空である可能性があります。

FindByIdメソッドを持つAPIは私を奇妙に思います。 APIにIDを与えている場合、呼び出し元は以前のAPI呼び出しでIDを何とか知っている可能性があることを意味しているため、APIはすでに存在するレコードを見つけ出す必要はありません。そのIDによって直接レコードを取得する方法を提供する必要があります。代わりに、レコードが存在するかどうかわからないときや、その他の基準を使用してレコードを検索する必要があります。

Webサービスの呼び出しを受けて、Webサービスの呼び出し元が何らかの形でIDを学習したので、GetByIdメソッドを呼び出すサービスに行きます。 idが存在しないと判明した場合、ライブラリはRecordNotFoundExceptionをスローする可能性があり、サービスコールが404を返す原因となります。

関連する問題