Flowsy.Db.Unity
5.0.0
dotnet add package Flowsy.Db.Unity --version 5.0.0
NuGet\Install-Package Flowsy.Db.Unity -Version 5.0.0
<PackageReference Include="Flowsy.Db.Unity" Version="5.0.0" />
<PackageVersion Include="Flowsy.Db.Unity" Version="5.0.0" />
<PackageReference Include="Flowsy.Db.Unity" />
paket add Flowsy.Db.Unity --version 5.0.0
#r "nuget: Flowsy.Db.Unity, 5.0.0"
#:package Flowsy.Db.Unity@5.0.0
#addin nuget:?package=Flowsy.Db.Unity&version=5.0.0
#tool nuget:?package=Flowsy.Db.Unity&version=5.0.0
Flowsy DB Unity
A .NET library that provides advanced functionality for accessing SQL databases with a configurable set of conventions and options for naming and formatting objects like tables, columns, routines, and parameters.
Installation
dotnet add package Flowsy.Db.Unity
Developer Documentation
See the usage guide for focused documentation about configuration, sessions, queries, routines, conventions, type mapping, migrations, transactions, and extensibility.
Features
- Multiple database providers: Compatible with PostgreSQL, SQL Server, MySQL, Oracle, and SQLite
- Configurable conventions: Customize column mapping, routine nomenclature, parameter usage, and data types
- Intelligent connection management: Automatic connection lifecycle management with transaction support
- Database sessions: Unified interface for CRUD operations with integrated logging
- Routine support: Execution of stored procedures and functions with specific conventions
- Dapper integration: High-level wrapper over Dapper with additional functionality
- Evolve migrations: Database migration support using Evolve
- Dependency injection: Fluent configuration through .NET's DI container
Core Architecture
Core Services
IDbConnectionFactory / DbConnectionFactory
Singleton service that creates database connections based on configurations identified by unique keys.
IDbConnectionHub / DbConnectionHub
Scoped service that manages database connections and controls their lifecycle, including opening, closing, and resource disposal.
IDbSession / DbSession
Represents a database session that allows performing query, execution, and transaction operations using Dapper as the underlying engine.
Basic Configuration
1. Service Registration
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Data.SqlClient;
using Npgsql;
using Flowsy.Db.Unity;
// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDatabases(options =>
{
// Configure PostgreSQL as default database
options
.UseConnection("MainDatabase", connectionString)
.AsDefault()
.WithProvider(DbProviderFamily.Postgres, "Npgsql", NpgsqlFactory.Instance)
.WithLogLevel(LogLevel.Debug)
.WithMigrations("/path/to/migrations")
.WithConventions()
.ForRoutines(DbRoutineType.StoredFunction)
.ForParameters(prefix: "p_", useNamedParameters: true)
.ForEnums(
typeNameCaseStyle: DbCaseStyle.LowerSnakeCase,
memberNameCaseStyle: DbCaseStyle.PascalCase,
mappings: [
new DbEnumMapping(typeof(ShoppingCartStatus), "shopping.shopping_cart_status"),
new DbEnumMapping(typeof(UserStatus), "accounts.user_status")
]
)
.WithDefault(DbCaseStyle.LowerSnakeCase);
// Type mapping for queries that return fields whose names are in lower_snake_case format.
// Databases like PostgreSQL and MySQL typically use this format by convention.
options.MapTypes(DbCaseStyle.LowerSnakeCase, types: [
typeof(Product),
typeof(ProductOverview),
typeof(ShoppingCart),
typeof(ShoppingCartOverview),
typeof(Category),
typeof(UserAccount)
]);
// Configure additional SQL Server for reports
options
.UseConnection("ReportsDatabase", reportsConnectionString)
.WithProvider(DbProviderFamily.SqlServer, "Microsoft.Data.SqlClient", SqlClientFactory.Instance)
.WithLogLevel(LogLevel.Information)
.WithConventions()
.ForParameters(prefix: "P_", useNamedParameters: true)
.WithDefault(DbCaseStyle.PascalCase);
// Type mapping for queries that return fields whose names are in PascalCase format.
// Databases like SQL Server typically use this format by convention.
options.MapTypes(DbCaseStyle.PascalCase, types: [
typeof(SalesReport),
typeof(MonthlyReport),
typeof(CustomerSummary)
]);
});
var app = builder.Build();
// ...
app.Run();
2. Usage in Controllers or Services
using Microsoft.Extensions.Logging;
using Flowsy.Db.Unity;
public class ProductService
{
private readonly IDbConnectionHub _connectionHub;
private readonly ILogger<ProductService> _logger;
public ProductService(IDbConnectionHub connectionHub, ILogger<ProductService> logger)
{
_connectionHub = connectionHub;
_logger = logger;
}
public async Task<IEnumerable<Product>> GetActiveProductsAsync()
{
// Use default connection (MainDatabase)
using var session = await _connectionHub.CreateSessionAsync("MainDatabase");
return await session.QueryAsync<Product>(
"SELECT product_id, name, price FROM products WHERE is_active = @p_is_active",
new { IsActive = true }
);
}
public async Task<Product?> GetProductByIdAsync(Guid productId)
{
using var session = await _connectionHub.CreateSessionAsync("MainDatabase");
return await session.QueryFirstOrDefaultAsync<Product>(
"SELECT * FROM products WHERE product_id = @p_product_id",
new
{
ProductId = productId
}
);
}
public async Task<Guid> CreateProductAsync(CreateProductRequest request)
{
using var session = await _connectionHub.CreateSessionAsync("MainDatabase");
// Use stored procedure
var result = await session.QuerySingleFromRoutineAsync<Guid>(
"create_product", // select * from create_product(p_name => @p_name, p_category_id => @p_category_id, p_price => @p_price);
new
{
Name = request.Name,
CategoryId = request.CategoryId,
Price = request.Price
}
);
return result;
}
}
3. Multiple Connection Usage
using Flowsy.Db.Unity;
public class ReportService
{
private readonly IDbConnectionHub _connectionHub;
public ReportService(IDbConnectionHub connectionHub)
{
_connectionHub = connectionHub;
}
public async Task<SalesReport> GenerateReportAsync(DateTime from, DateTime to)
{
// Use specific connection for reports
using var session = await _connectionHub.CreateSessionAsync("ReportsDatabase");
return await session.QueryFirstFromRoutineAsync<SalesReport>(
"generate_sales_report", // EXEC generate_sales_report @FromDate = @P_FromDate, @P_ToDate = @P_ToDate;
new
{
FromDate = from,
ToDate = to
}
);
}
}
Transactions
using Flowsy.Db.Unity;
public async Task TransferFundsAsync(Guid fromAccountId, Guid toAccountId, decimal amount)
{
using var session = await _connectionHub.CreateSessionAsync("MainDatabase");
session.BeginTransaction();
try
{
// Debit source account
await session.ExecuteAsync(
"UPDATE accounts SET balance = balance - @p_amount WHERE account_id = @p_account_id",
new
{
Amount = amount,
AccountId = fromAccountId
}
);
// Credit destination account
await session.ExecuteAsync(
"UPDATE accounts SET balance = balance + @p_amount WHERE account_id = @p_account_id",
new
{
Amount = amount,
AccountId = toAccountId
}
);
await session.CommitTransactionAsync();
}
catch(Exception exception)
{
// Error logging
// _logger.LogError(exception, "Error during fund transfer");
// No need to call RollbackTransactionAsync() explicitly
// IDbSession performs rollback automatically when exiting the
// code block where the session was created (TransferFundsAsync method)
throw;
}
}
Script Execution
using Flowsy.Db.Unity;
// For migrations or database initialization
using var session = await _connectionHub.CreateSessionAsync("MainDatabase");
// Execute individual script
await session.ExecuteScriptAsync("path/to/script.sql");
// Execute script folder
await session.ExecuteScriptAsync("path/to/scripts/");
// Execute migrations according to Evolve conventions (versioned and repeatable)
await session.MigrateAsync();
IDbSession Methods
Query Operations
Queries that return multiple results
QueryAsync<T>()- Returns multiple results asIEnumerable<T>QueryFromRoutineAsync<T>()- Returns multiple results from routine asIEnumerable<T>
Queries that return the first result
QueryFirstAsync<T>()- First result (throws exception if no results found)QueryFirstFromRoutineAsync<T>()- First result from routine (throws exception if no results found)QueryFirstOrDefaultAsync<T>()- First result or default value if no results foundQueryFirstOrDefaultFromRoutineAsync<T>()- First result from routine or default value
Queries that return a single result
QuerySingleAsync<T>()- Single result (throws exception if no results or multiple results found)QuerySingleFromRoutineAsync<T>()- Single result from routine (throws exception if no results or multiple found)QuerySingleOrDefaultAsync<T>()- Single result or default value (throws exception if multiple found)QuerySingleOrDefaultFromRoutineAsync<T>()- Single result from routine or default value
Queries with multiple result sets
QueryMultipleAsync()- Returns multiple result sets in a single queryQueryMultipleFromRoutineAsync()- Returns multiple result sets from routine
Execution Operations
Command execution
ExecuteAsync()- Executes SQL statement (INSERT, UPDATE, DELETE) and returns affected rowsExecuteRoutineAsync()- Executes stored procedure or function and returns affected rows
Script Operations
ExecuteScriptAsync()- Executes SQL script from file or folder
Transaction Operations
BeginTransaction()- Starts a transactionCommitTransactionAsync()- Commits the current transactionRollbackTransactionAsync()- Rolls back the current transaction
Method Parameters
All Dapper wrapper methods accept the following parameters:
string statementorstring routineName: SQL statement or routine name to execute.dynamic? parameters = null: Dynamic parameters (anonymous object) for the query or routine.CancellationToken cancellationToken = default: Token to cancel the asynchronous operation.
Logging
All operations include structured logging with unique session and operation identifiers:
[SESSION:{SessionId} > OP:{OperationId}] {Message}
[SESSION:{SessionId} > OP:{OperationId}] {Message}
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. 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. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- CaseON (>= 1.4.0)
- Dapper (>= 2.1.79)
- Evolve (>= 3.2.0)
- Microsoft.Extensions.Configuration (>= 10.0.8)
- Microsoft.Extensions.Configuration.Json (>= 10.0.8)
- Microsoft.Extensions.Hosting (>= 10.0.8)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.8)
- Ulid (>= 1.4.1)
-
net8.0
- CaseON (>= 1.4.0)
- Dapper (>= 2.1.79)
- Evolve (>= 3.2.0)
- Microsoft.Extensions.Configuration (>= 8.0.0)
- Microsoft.Extensions.Configuration.Json (>= 8.0.1)
- Microsoft.Extensions.Hosting (>= 8.0.1)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.3)
- Ulid (>= 1.4.1)
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 |
|---|---|---|
| 5.0.0 | 91 | 6/8/2026 |
| 4.0.4 | 208 | 11/15/2025 |
| 4.0.3 | 221 | 9/25/2025 |
| 4.0.2 | 223 | 9/25/2025 |
| 4.0.1 | 227 | 9/24/2025 |
| 4.0.0 | 272 | 9/14/2025 |
| 3.0.0 | 376 | 6/12/2025 |
| 2.0.5 | 340 | 6/9/2025 |
| 2.0.4 | 364 | 6/9/2025 |
| 2.0.3 | 340 | 6/9/2025 |
| 2.0.2 | 346 | 6/9/2025 |
| 2.0.1 | 157 | 6/6/2025 |
| 2.0.0 | 213 | 6/1/2025 |
| 1.2.1 | 228 | 6/1/2025 |
| 1.2.0 | 165 | 5/25/2025 |
| 1.1.0 | 162 | 5/25/2025 |
| 1.0.0 | 187 | 5/18/2025 |