Имея два класса:
public class Parent
{
public int Id { get; set; }
public int ChildId { get; set; }
}
public class Child { ... }
При назначении ChildIdна Parentя должен проверить первый , если он существует в БД или ждать DB бросить исключение?
Например (с использованием Entity Framework Core):
ЗАМЕТЬТЕ, что эти виды проверок ВСЕ В ИНТЕРНЕТЕ, даже в официальных документах Microsoft: https://docs.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using- mvc / processing-Concurrency-Concurrency-with-the-entity-framework-in-an-asp-net-mvc-application # modify-the-Department-controller, но есть дополнительная обработка исключенийSaveChanges
Также обратите внимание, что основной целью этой проверки было вернуть дружественное сообщение и известный статус HTTP пользователю API, а не полностью игнорировать исключения базы данных. И единственное место, которое будет выброшено - внутри 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
Недостаток обработки исключений таким способом в ORM, как EF, заключается в том, что он будет работать только с определенной базой данных базы данных. Если вы когда-либо хотели переключиться на SQL-сервер или что-то еще, это больше не будет работать, потому что код ошибки изменится.
Неправильное форматирование исключения для конечного пользователя может раскрыть некоторые вещи, которые вы не хотите, чтобы кто-либо кроме разработчиков видел.
Связанный:
https://stackoverflow.com/questions/308905/should-there-be-a-transaction-for-read-queries
Child with id {parent.ChildId} could not be found.. И форматирование «Нарушение внешнего ключа», я думаю, хуже в этом случае.