Tener dos clases:
public class Parent
{
public int Id { get; set; }
public int ChildId { get; set; }
}
public class Child { ... }
Al asignar ChildId
a Parent
debería comprobar primero si existe en la base de datos o esperar a que la base de datos a una excepción?
Por ejemplo (usando Entity Framework Core):
TENGA EN CUENTA que este tipo de comprobaciones ESTÁN EN TODA LA INTERNET incluso en los documentos oficiales de 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 # modify-the-department-controller pero hay un manejo adicional de excepciones paraSaveChanges
Además, tenga en cuenta que la intención principal de esta comprobación fue devolver un mensaje amigable y un estado HTTP conocido al usuario de la API y no ignorar por completo las excepciones de la base de datos. Y el único lugar en el que se lanzará una excepción es dentro SaveChanges
o SaveChangesAsync
llamando ... para que no haya ninguna excepción cuando llame FindAsync
o Any
. Por lo tanto, si existe un elemento secundario pero se eliminó antes, SaveChangesAsync
se generará una excepción de concurrencia.
Hice esto debido a que la foreign key violation
excepción será mucho más difícil de formatear para mostrar "No se pudo encontrar el niño con 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;
}
versus:
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;
}
El segundo ejemplo en Postgres arrojará un 23503 foreign_key_violation
error: https://www.postgresql.org/docs/9.4/static/errcodes-appendix.html
La desventaja de manejar excepciones de esta manera en ORM como EF es que solo funcionará con un backend de base de datos específico. Si alguna vez quisiste cambiar al servidor SQL o algo más, esto ya no funcionará porque el código de error cambiará.
No formatear la excepción correctamente para el usuario final podría exponer algunas cosas que no desea que nadie más que los desarrolladores vean.
Relacionado:
https://stackoverflow.com/questions/308905/should-there-be-a-transaction-for-read-queries
Child with id {parent.ChildId} could not be found.
. Y formatear "Violación de clave externa" creo que es peor en este caso.