Имея два класса:
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.
. И форматирование «Нарушение внешнего ключа», я думаю, хуже в этом случае.