Sviluppiamo su un'API Web ASP.NET in cui utilizziamo il modello "Unità di lavoro / deposito":
I nostri controllori hanno questo aspetto:
public class MyController : Controller
{
private IUnitOfWork _unitOfWork;
private IMyService _myService;
public MyController(IUnitOfWork unitOfWork, IMyService myService)
{
_unitOfWork = unitOfWork;
_myService = myService;
}
[HttpPost]
public IActionResult CreateItem(Item item)
{
try
{
_unitOfWork.BeginTransaction();
_myService.CreateItem(item);
_unitOfWork.Commit();
}
catch (Exception e)
{
// Transaction failed, we must rollback to keep a consistent state
_unitOfWork.Rollback();
// Logging
//...
// Return HTTP 500 Error
return StatusCode(Microsoft.AspNetCore.Http.StatusCodes.Status500InternalServerError);
}
return StatusCode(Microsoft.AspNetCore.Http.StatusCodes.Status200OK);
}
}
Avremo più controller con la stessa logica:
- Avvia una transazione
- Esegui la logica aziendale
- Conferma le modifiche
- Gestire eventuali eccezioni (rollback, log, restituire lo stato HTTP appropriato)
Quindi, ci stiamo chiedendo se possiamo "centralizzare" questo codice per evitare la duplicazione
Solo la logica aziendale sarà diversa
In questa classe:
_myService.CreateItem(item);
È davvero una buona idea?
E se sì quale modello sarebbe il migliore?
Modifica
Dopo ulteriori indagini, sembra che l'unica cosa che dobbiamo davvero centralizzare sia la gestione delle eccezioni
In questo caso avremmo questo tipo di controller:
public class MyController : Controller
{
private IUnitOfWork _unitOfWork;
private IMyService _myService;
public MyController(IUnitOfWork unitOfWork, IMyService myService)
{
_unitOfWork = unitOfWork;
_myService = myService;
}
[HttpPost]
public void CreateItem(Item item)
{
using (var uow = _unitOfWork.BeginTransaction())
{
_myService.CreateItem(item);
_unitOfWork.Commit();
}
}
}
La gestione delle eccezioni sarebbe centralizzata con ExceptionFilter come spiegato qui:
Per il rollback, sembra che non sia necessario gestirlo manualmente: