Posiadanie dwóch klas:
public class Parent
{
public int Id { get; set; }
public int ChildId { get; set; }
}
public class Child { ... }
Przy przypisywaniu ChildId
do Parent
powinienem najpierw sprawdzić, czy istnieje w bazie danych, czy poczekać, aż baza danych zgłosi wyjątek?
Na przykład (przy użyciu Entity Framework Core):
UWAGA: tego rodzaju kontrole są WSZYSTKIE W INTERNECIE, nawet w oficjalnych dokumentach Microsoftu: 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-net-mvc-application # zmodyfikuj kontroler departamentu, ale istnieje dodatkowa obsługa wyjątków dlaSaveChanges
należy również zauważyć, że głównym celem tego sprawdzenia było zwrócenie przyjaznego komunikatu i znanego statusu HTTP użytkownikowi interfejsu API, a nie całkowite zignorowanie wyjątków bazy danych. Jedyny wyjątek od miejsca, który zostanie zgłoszony, to wnętrze SaveChanges
lub SaveChangesAsync
połączenie ... więc nie będzie żadnego wyjątku podczas połączenia FindAsync
lub Any
. Jeśli więc dziecko istnieje, ale zostało usunięte wcześniej, SaveChangesAsync
zostanie zgłoszony wyjątek współbieżności.
Zrobiłem to, ponieważ foreign key violation
wyjątek będzie znacznie trudniejszy do sformatowania w celu wyświetlenia „Nie można znaleźć elementu podrzędnego o identyfikatorze {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;
}
przeciw:
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;
}
Drugi przykład w Postgres zgłosi 23503 foreign_key_violation
błąd: https://www.postgresql.org/docs/9.4/static/errcodes-appendix.html
Wadą obsługi wyjątków w ten sposób w ORM, takich jak EF, jest to, że będzie działać tylko z określonym zapleczem bazy danych. Jeśli kiedykolwiek chciałeś przełączyć się na serwer SQL lub coś innego, nie będzie to już działać, ponieważ kod błędu się zmieni.
Niepoprawne sformatowanie wyjątku dla użytkownika końcowego może ujawnić pewne rzeczy, których nikt poza deweloperami nie powinien widzieć.
Związane z:
https://stackoverflow.com/questions/308905/should-there-be-a-transaction-for-read-queries
Child with id {parent.ChildId} could not be found.
. A formatowanie „Naruszenie klucza obcego” wydaje mi się gorsze w tym przypadku.