Маючи два класи:
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 / handling-concurrency-with-the-object-Framework-in-as-asp-net-mvc-application # modify-the-отдел-контролер, але є додаткова обробка виключень дляSaveChanges
також зауважте, що основною метою цієї перевірки було повернути користувачеві API дружнє повідомлення та відомий статус HTTP та не повністю ігнорувати винятки з бази даних. І єдине місце , при виникненні виключення всередині SaveChanges
або SaveChangesAsync
виклик ... так що не буде якихось - яких винятків , коли ви телефонуєте FindAsync
або Any
. Тож, якщо дитина існує, але її було видалено до SaveChangesAsync
цього, буде викинуто виняток з одночасності.
Я зробив це через те, що foreign key violation
виняток буде набагато складніше форматувати для відображення "Child with 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.
. І форматування "Порушення закордонних ключів" я думаю, що в цьому випадку гірше.