Promethix.Framework.Ado 0.1.32-alpha

This is a prerelease version of Promethix.Framework.Ado.
There is a newer version of this package available.
See the version list below for details.
dotnet add package Promethix.Framework.Ado --version 0.1.32-alpha                
NuGet\Install-Package Promethix.Framework.Ado -Version 0.1.32-alpha                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Promethix.Framework.Ado" Version="0.1.32-alpha" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Promethix.Framework.Ado --version 0.1.32-alpha                
#r "nuget: Promethix.Framework.Ado, 0.1.32-alpha"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Promethix.Framework.Ado as a Cake Addin
#addin nuget:?package=Promethix.Framework.Ado&version=0.1.32-alpha&prerelease

// Install Promethix.Framework.Ado as a Cake Tool
#tool nuget:?package=Promethix.Framework.Ado&version=0.1.32-alpha&prerelease                

AdoScope (Pre-Release Alpha)

Build and Test 0.1.x-alpha Published to nuget.org 0.1.x-alpha

AdoScope offers a simple and flexible solution for managing your ADO.NET connections and transactions. It draws inspiration from the remarkable work in DbContextScope by Mehdime El Gueddari, whose DbContextScope library has been a source of great inspiration for the creation of AdoScope.

While AdoScope is compatible with any ADO.NET provider, it was specifically designed with Dapper in mind. Having extensive experience with Entity Framework and DbContextScope, the goal was to provide a similar solution tailored to the requirements of Dapper.

Unlike Entity Framework, Dapper lacks a DbContext, which can lead to challenges in managing DbConnection and DbTransaction. To address this, AdoScope introduces the concept of an AdoContext—a wrapper around DbConnection and DbTransaction, simplifying their management.

If you are seeking a Unit of Work pattern for Dapper with minimal coding overhead, AdoScope provides an elegant solution.

Features

  • Simple and flexible configuration
  • Database provider agnostic
  • Support for nested transactions
  • Support for multiple database connections
  • Support for explicit database transactions
  • Context specific execution options (transactional, non-transactional)
  • Support for specific isolation levels per context and per (explicit) transaction

Future Features

  • Support for multiple databases in a single distributed transaction
  • Support for explicit distributed transactions
  • Support for read only transactions
  • Support for asynchronous operations

Please be aware

That when your AdoContext is configured in transactional mode, it will hold a transaction open until you call Complete() or Dispose() on the AdoScope, this is by design. If you do not want this behavior, configure your AdoContext to be non-transactional.

CreateWithTransaction() forces the creation of a new ambient AdoContext (i.e. does not join the ambient scope if there is one) and wraps all AdoContext instances created within that scope in an explicit database transaction with the provided isolation level.

Usage

Install the NuGet package

Install-Package AdoScope -Version 0.1.30-alpha

Create an ADO Context

public class SqliteContextExample1 : AdoContext
    {
        public SqliteContextExample1()
        {
            // No Implementation
        }
    }

Create a Repository making use of this context

public class SimpleTestRepository : ISimpleTestRepository
{
    private readonly IAmbientAdoContextLocator ambientAdoContextLocator;

    public SimpleTestRepository(IAmbientAdoContextLocator ambientAdoContextLocator)
    {
        this.ambientAdoContextLocator = ambientAdoContextLocator;
    }

    private IDbConnection SqliteConnection => ambientAdoContextLocator.GetContext<SqliteContextExample1>().Connection;

    public void Add(TestEntity entity)
    {
        const string query = "INSERT INTO TestEntity (Name, Description, Quantity) VALUES (@Name, @Description, @Quantity)";
        SqliteConnection.Execute(query, entity);
    }

    public TestEntity GetEntityByName(string name)
    {
        const string query = "SELECT * FROM TestEntity WHERE Name = @Name";
        return SqliteConnection.QuerySingleOrDefault<TestEntity>(query, new { Name = name });
    }
}

Create a Service making use of this repository and AdoScope.

When the ADO Context is configured with a transactional execution option, this will behave as a Unit of Work. It will commit when Complete() is called.

You can also configure the ADO Context to be non-transactional, in which case it will behave as a simple connection manager, executing queries as they are called.

public void ServiceLayerAddTestEntity()
{
    using IAdoScope adoScope = adoScopeFactory.Create();

    // Create a test entity
    var newTestEntity = new TestEntity { Name = "CreateTest", Description = "Test Description", Quantity = 1 };

    // Call our repository to add the entity
    simpleTestRepository.Add(newTestEntity);

    // Commit the unit of work / transaction (if using ExecutionOption.Transactional)
    adoScope.Complete();
}

Configure your DI Container. Just one of many examples of configuration. This example is by hand to show the available options. Recommend you use appsettings.json for configuration. See example below this one for that.

// Still need to register ADO providers you will be using. This is a .NET ADO requirement.
DbProviderFactories.RegisterFactory("Microsoft.Data.Sqlite", SqliteFactory.Instance);

// Register your repositories et al
_ = services.AddSingleton<IAmbientAdoContextLocator, AmbientAdoContextLocator>();
_ = services.AddSingleton<IAdoScopeFactory, AdoScopeFactory>();
_ = services.AddSingleton<IAdoContextGroupFactory, AdoContextGroupFactory>();
_ = services.AddScoped<ISimpleTestRepository, SimpleTestRepository>();
_ = services.AddScoped<IMultiTestRepository, MultiTestRepository>();

// Register your ADO Contexts
var adoContextConfiguration = new AdoContextConfigurationBuilder()
.AddAdoContext<SqliteContextExample1>(options =>
{
    _ = options.WithNamedConnection("SqliteContextExample");
    _ = options.WithConnectionString("Data Source=mydatabase.db");
    _ = options.WithProviderName("Microsoft.Data.Sqlite");
    _ = options.WithExecutionOption(AdoContextExecutionOption.Transactional);
    _ = options.WithDefaultIsolationLevel(IsolationLevel.ReadCommitted);
})
.Build();

_ = services.AddScoped(provider => adoContextConfiguration);  

Recommended approach

Use appsettings.json for configuration, you can use the following code. In your DI registrations:

// Create ADO context configuration
var adoContextConfiguration = new AdoContextConfigurationBuilder()
.AddAdoContext<SqliteContextExample1>(options =>
{
    _ = options.WithNamedConnection("SqliteContextExample1", configuration);
})
.Build();

// Register your ADO context configuration
_ = services.AddScoped(provider => adoContextConfiguration);  

appsettings.json as follows (see unit test project for more examples):

{
  "AdoContextOptions": {
    "SqliteContextExample1": {
      "ProviderName": "Microsoft.Data.Sqlite",
      "ExecutionOption": "Transactional"
    }
  },
  "ConnectionStrings": {
    "SqliteContextExample1": "Data Source=mydatabase.db",
  }
}

For MS SQL Server the Provider Name should be System.Data.SqlClient

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Framework net48 is compatible.  net481 was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.0 122 5/2/2024
1.0.0-rc4 215 1/17/2024
1.0.0-rc3 118 1/15/2024
1.0.0-rc2 188 11/19/2023
1.0.0-rc1 119 11/9/2023
0.1.42-alpha 119 11/6/2023
0.1.39-alpha 118 10/17/2023
0.1.32-alpha 124 10/14/2023
0.1.30-alpha 110 9/30/2023
0.1.29-alpha 114 9/28/2023
0.1.28-alpha 106 9/28/2023
0.1.24-alpha 111 9/25/2023
0.1.20-alpha 111 9/24/2023
0.1.7-alpha 109 9/23/2023