Avere due lezioni:
public class Parent
{
public int Id { get; set; }
public int ChildId { get; set; }
}
public class Child { ... }
Quando si assegna ChildId
a Parent
, devo prima verificare se esiste nel DB o attendere che il DB generi un'eccezione?
Ad esempio (utilizzando Entity Framework Core):
NOTA: questi tipi di controlli sono in TUTTA L'INTERNET anche sui documenti ufficiali di Microsoft: 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 # change-the-department-controller ma esiste un'ulteriore gestione delle eccezioni perSaveChanges
inoltre, si noti che l'intento principale di questo controllo era di restituire un messaggio descrittivo e lo stato HTTP noto all'utente dell'API e di non ignorare completamente le eccezioni del database. E l'unica posizione in cui viene generata l'eccezione è dentro SaveChanges
o SaveChangesAsync
chiama ... quindi non ci sarà alcuna eccezione quando chiami FindAsync
o Any
. Pertanto, se esiste un figlio ma è stato eliminato prima, SaveChangesAsync
verrà generata un'eccezione di concorrenza.
L'ho fatto a causa del fatto che l' foreign key violation
eccezione sarà molto più difficile da formattare per visualizzare "Il bambino con 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;
}
contro:
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 in Postgres genererà un 23503 foreign_key_violation
errore: https://www.postgresql.org/docs/9.4/static/errcodes-appendix.html
L'aspetto negativo di gestire le eccezioni in questo modo in ORM come EF è che funzionerà solo con uno specifico back-end del database. Se hai mai voluto 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 potrebbe esporre alcune cose che non si desidera vedere a nessuno, ma agli sviluppatori.
Relazionato:
https://stackoverflow.com/questions/308905/should-there-be-a-transaction-for-read-queries
Child with id {parent.ChildId} could not be found.
. E la formattazione di "Violazione della chiave esterna" penso che in questo caso sia peggio.