Sto utilizzando EF Core 2.0 con i modelli Repository e Unit of Work. Qual è il modo migliore per gestire tutte le eccezioni db ?. Posso usare try / catch nel mio metodo di commit?
public void Commit()
{
try
{
_context.SaveChanges();
}
catch (Exception ex)
{
//code
}
}
Può qualcosa oltre a SaveChanges()
lanciare un'eccezione? Cosa dovrebbe fare in seguito con l'eccezione rilevata?
Ti darei un esempio di come implementerei personalmente, forse puoi migliorarlo secondo le tue esigenze ma almeno hai un buon punto di partenza.
Crea un middleware che gestirà le eccezioni in generale come di seguito:
public class ErrorHandlingMiddleware
{
private readonly RequestDelegate _next;
public ErrorHandlingMiddleware(RequestDelegate next)
{
this._next = next;
}
public async Task Invoke(HttpContext context, ILogger logger)
{
try
{
await _next(context);
}
catch (Exception ex)
{
await HandleExceptionAsync(context, ex, logger);
}
}
private static Task HandleExceptionAsync(HttpContext context, Exception exception, ILogger logger)
{
if(exception is DbException)
{
//Do something else if needed
}
logger.Log(exception);
//do something
return context.Response.WriteAsync(... something ...); //Maybe some JSON message or something
}
}
Quindi registra il middleware come di seguito nel metodo configure:
app.UseMiddleware<ErrorHandlingMiddleware>();
DbException
potrebbe essere solo un'eccezione personalizzata che potresti lanciare o puoi inserire altri tipi di eccezioni esistenti se vuoi gestirli diversamente.
Nel caso tu stia utilizzando ASP.NET MVC puoi avere un BaseController
e usarlo qui :
La seconda opzione che ho usato personalmente è implementando l'unità di lavoro come di seguito.
using (var unitOfWork = UnitOfWorkManager.NewUnitOfWork()) { if (ModelState.IsValid) { //Do Stuff try { unitOfWork.Commit(); } catch (Exception e) { unitOfWork.Rollback(); LoggingService.LogCommitException(e); } } }
La seconda opzione è a volte più preferibile se si desidera includere più codice di logica aziendale quando si verifica un'eccezione.
Nel tuo caso vai con la seconda opzione, ma potresti includere entrambe le opzioni nella soluzione in quanto il middleware può catturare anche altre eccezioni globali.
Suggerirei di non includere alcun metodo try-catch
all'interno del commit perché non è responsabilità rilevare eventuali eccezioni, tanto più si dovrebbe iniettare un logger all'interno del gestore di UnitOfWork
che può essere emesso. Quindi, per concludere che il metodo di commit
deve solo impegnarsi, altre azioni dovrebbero essere al di fuori del suo ambito.