2つのクラスがある:
public class Parent
{
public int Id { get; set; }
public int ChildId { get; set; }
}
public class Child { ... }
割り当てるときChildId
にParent
、それが例外をスローするDB用DBまたは待機中に存在する場合、私が最初に確認する必要がありますか?
例(Entity Framework Coreを使用):
注:これらの種類のチェックは、Microsoftの公式ドキュメントでもインターネット全体で行われます:https : //docs.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using- mvc / handling-concurrency-with-the-entity-framework-in-an-asp-mvc-application#modify-the-department-controllerしかし、追加の例外処理があります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の2番目の例は23503 foreign_key_violation
エラーをスローします:https : //www.postgresql.org/docs/9.4/static/errcodes-appendix.html
EFのようなORMでこのように例外を処理する欠点は、特定のデータベースバックエンドでのみ機能することです。エラーコードが変更されるため、SQLサーバーまたは他の何かに切り替えたい場合、これはもう機能しません。
例外をエンドユーザー向けに適切にフォーマットしないと、開発者以外には見られたくないものが明らかになる可能性があります。
関連:
https://stackoverflow.com/questions/308905/should-there-be-a-transaction-for-read-queries
Child with id {parent.ChildId} could not be found.
。そして、この場合、「外部キー違反」のフォーマットが悪いと思います。