如果在数据库中找不到记录,是否返回(RecordNotFound)异常或null
本文关键字:RecordNotFound 异常 null 返回 是否 数据库 找不到 记录 如果 | 更新日期: 2023-09-27 18:04:14
我真的不确定在处理数据库中找不到的记录时,首选的方法是什么。写返回null的Find方法更好还是写返回RecordNotFoundException
的Get方法更好?
[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);
}
更新
与我的同事交谈后,我们决定采用这个解决方案。至于为什么GetActivity返回null而不是抛出Exception,我更喜欢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);
}
}
这两种方式都是有效的。
无论使用异常还是返回值null
来表示不存在的记录,重点都不同。
存在异常以表示错误状态(发生了异常情况(。catch
处理程序中的代码集中于如何处理错误而不包含业务逻辑。
如果返回null
,那么它将是模型中的正常和"非异常"状态。
因此,如果在您的域中可能发生这种情况,则返回null
,即记录不存在(根据我的经验,这种情况最常见(。如果您希望记录存在,但它不存在,那么抛出exception
是有效的。
我不同意另一个答案。在GetyById方法的情况下,我不会说返回null而不是抛出,因为你可能会认为"预期"可能没有具有请求id的记录。这种"特殊情况下的例外"虽然经常被提及,但我真的不认为是思考该方法的合同的最佳方式。理想情况下,API应该具有语义意义。
相反,我建议在方法无法执行命令时抛出异常。因此,如果系统中没有具有请求id的记录,GetById方法应该抛出异常。Find方法可能应该返回一个可枚举值,当然,如果没有符合给定条件的记录,该值可能为空。
一个有FindById方法的API让我觉得很奇怪;如果你给API一个ID,这意味着调用者可能已经在以前的API调用中学习了ID,因此API不需要"找到"一个已知存在的记录。它应该提供一种直接通过id获取记录的方法。相反,Find应该用于在您不确定记录是否存在时定位记录,并使用其他一些标准。
给定web服务调用,我将使用调用GetById方法的服务,因为web服务调用方也不知何故了解了id。如果id不存在,库可以抛出RecordNotFoundException,这将导致服务调用返回404。