Con due classi:
public class Parent
{
public int Id { get; set; }
public int ChildId { get; set; }
}
public class Child { ... }
Quando assegni ChildId
a Parent
dovrei controllare prima se esiste nel DB o aspettare che il DB lanci un'eccezione?
Ad esempio (utilizzando Entity Framework Core):
NOTA questi tipi di controlli sono ALL OVER THE INTERNET anche sui documenti ufficiali di Microsoft: link ma esiste un'ulteriore gestione delle eccezioni per SaveChanges
Inoltre, si noti che l'intento principale di questo controllo era di restituire il messaggio amichevole e lo stato HTTP noto all'utente dell'API e di non ignorare completamente le eccezioni del database. E l'unica eccezione del luogo che viene generata è all'interno di SaveChanges
o SaveChangesAsync
call ... quindi non ci saranno eccezioni quando chiami FindAsync
o Any
. Quindi, se il figlio esiste ma è stato eliminato prima di SaveChangesAsync
, verrà lanciata un'eccezione di concorrenza.
L'ho fatto a causa del fatto che l'eccezione foreign key violation
sarà molto più difficile da formattare per visualizzare "Child with id {parent.ChildId} non è stato trovato."
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;
}
vs
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;
}
Il secondo esempio di Postgres genererà l'errore 23503 foreign_key_violation
: link
Lo svantaggio di gestire le eccezioni in questo modo in ORM come EF è che funzionerà solo con un database specifico back-end. Se hai mai desiderato passare al server SQL o qualcos'altro, questo non funzionerà più perché il codice di errore cambierà.
Non formattare correttamente l'eccezione per l'utente finale potresti esporre alcune cose che non vuoi che siano gli sviluppatori a vedere.
Related: