有两节课:
public class Parent
{
public int Id { get; set; }
public int ChildId { get; set; }
}
public class Child { ... }
分配给时ChildId
,Parent
我应该首先检查数据库中是否存在它,或者等待数据库引发异常?
例如(使用实体框架核心):
注意,即使在官方的Microsoft文档中,这类检查也已遍及整个Internet:https://docs.microsoft.com/zh-cn/aspnet/mvc/overview/getting-started/getting-started-with-ef-using- MVC /处理与实体框架在ASP.NET MVC应用程序中的并发处理#修改部门控制器,但还有其他异常处理SaveChanges
另外,请注意,此检查的主要目的是向API用户返回友好消息和已知的HTTP状态,而不是完全忽略数据库异常。并且唯一引发异常的地方是在内部SaveChanges
或SaveChangesAsync
调用中...因此,当您调用FindAsync
或时不会有任何异常Any
。因此,如果子项存在但在此之前被删除,SaveChangesAsync
则将引发并发异常。
我这样做的原因是,foreign key violation
异常将很难格式化以显示“找不到ID为{parent.ChildId}的孩子”。
public async Task<ActionResult<Parent>> CreateParent(Parent parent)
{
// is this code redundant?
// NOTE: its probably better to use Any isntead of FindAsync because FindAsync selects *, and Any selects 1
var child = await _db.Children.FindAsync(parent.ChildId);
if (child == null)
return NotFound($"Child with id {parent.ChildId} could not be found.");
_db.Parents.Add(parent);
await _db.SaveChangesAsync();
return parent;
}
与:
public async Task<ActionResult<Parent>> CreateParent(Parent parent)
{
_db.Parents.Add(parent);
await _db.SaveChangesAsync(); // handle exception somewhere globally when child with the specified id doesn't exist...
return parent;
}
Postgres中的第二个示例将引发23503 foreign_key_violation
错误:https : //www.postgresql.org/docs/9.4/static/errcodes-appendix.html
在像EF这样的ORM中以这种方式处理异常的不利之处在于,它仅适用于特定的数据库后端。如果您想切换到SQL Server或其他服务器,则此命令将不再起作用,因为错误代码将更改。
如果没有为最终用户正确设置异常的格式,则可能会暴露一些您除了开发人员以外都不希望看到的东西。
有关:
https://stackoverflow.com/questions/308905/should-there-be-a-transaction-for-read-queries
Child with id {parent.ChildId} could not be found.
。在这种情况下,格式化“外键违规”的情况更糟。