Skip to content

ASP.NET Persistence Module

When working with ASP.NET, the Suite provides a Middleware that implements a Unit of Work per-request strategy. Basically, a single Unit of work will be created, and its lifetime handled, automatically.

The behavior of the Unit of Work is determined by the HTTP Request method, and the chosen UnitOfWorkStrategy.

If the HTTP Request method is GET, a Unit of Work with no associated transaction will be created. Otherwise, the behavior will depend on the selected strategy:

  • UnitOfWorkStrategy.AutoCommit: a transaction will be created before calling the next middleware in the pipeline, and it will be committed after that middleware returns. This is the default value if not overridden.
  • UnitOfWorkStrategy.ManualCommit: a transaction will be created before calling the next middleware in the pipeline, but won't be committed nor rolled back after that middleware returns. Read below how to commit.
  • UnitOfWorkStrategy.AlwaysRollback: a transaction will be created before calling the next middleware in the pipeline, and it will be rolled back after that middleware returns.
  • UnitOfWorkStrategy.Disabled: no unit of work will be created.

The default UnitOfWorkStrategy can be overridden by configuration, either through AspNetPersistenceModuleOptions, or by using the [UnitOfWorkStrategy] attribute on the IAppService class, or the method inside an App Service.

Using the ManualCommit strategy

When using the ManualCommit you'll need to commit the transaction manually. In order to do so, you can use the IUnitOfWorkManager.Current:

C#
internal class MyAppService : IAppService
{
    private readonly IUnitOfWorkManager unitOfWorkManager;

    public MyAppService(IUnitOfWorkManager unitOfWorkManager)
    {
        this.unitOfWorkManager = unitOfWorkManager;
    }

    [UnitOfWorkStrategy(UnitOfWorkStrategy.ManualCommit)]
    public void DoTransactionalWork(CancellationToken ct)
    {
        try
        {
            // do something here which affects the database
            this.unitOfWorkManager.Current.CompleteAsync(ct);
        }
        catch (Exception)
        {

            this.unitOfWorkManager.Current.RollbackAsync(ct);
            throw;
        }
    }
}

Default values from Configuration

Important

Whenever possible, try to use the default AutoCommit behavior and avoid configuration or attribute customization.

The ASP.NET Persistence Module can be configured through IConfiguration.

By code, when depending on the module:

C#
internal class AdminCenterApplicationModule : SuiteAspNetApplicationModule
{
    public override void SetupModule(IModuleBuilder builder)
    {
        base.SetupModule(builder);

        builder.DependsOn<AspNetPersistenceModule, AspNetPersistenceModuleOptions>(ops=> {
            ops.UnitOfWorkStrategy = UnitOfWorkStrategy.ManualCommit;
        });
    }
}

Or through other means like the appsettings.json:

JSON
1
2
3
4
5
{
    "ITsynch.Suite.App.Modules.AspNetPersistenceModule": {
        "UnitOfWorkStrategy": "UnitOfWorkStrategy.ManualCommit"
    }
}

Using the [UnitOfWorkStrategy]

In the below example, the Unit of Work will be rolled back by default after every request.

The Calculate method, will be rolled back automatically due to the class attribute. The Create method will be automatically committed, if no exceptions are thrown during the execution of the request.

C#
[UnitOfWorkStrategy(UnitOfWorkStrategy.AlwaysRollback)]
public class InspectionsAppService : IAppService
{
    public async Task<int> Calculate(
        CancellationToken ct = default)
    {
        return await this.inspectionRepository.DoSomeMath(123, ct);
    }

    [UnitOfWorkStrategy(UnitOfWorkStrategy.AutoCommit)]
    public async Task<InspectionOutputDTO> Create(
        CreateInspectionInputDTO inspection,
        CancellationToken ct = default)
    {
        var newInspection = new Inspection { Description = inspection.Description };
        await this.inspectionRepository.CreateAsync(newInspection, ct);
        return this.mapper.Map<InspectionOutputDTO>(newInspection);
    }
}