![]() |
VOOZH | about |
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" />Directory.Packages.props
<PackageReference Include="Flowsy.Db.Unity" />Project file
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.0Install as a Cake Addin
#tool nuget:?package=Flowsy.Db.Unity&version=5.0.0Install as a Cake Tool
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.
dotnet add package Flowsy.Db.Unity
See the for focused documentation about configuration, sessions, queries, routines, conventions, type mapping, migrations, transactions, and extensibility.
IDbConnectionFactory / DbConnectionFactorySingleton service that creates database connections based on configurations identified by unique keys.
IDbConnectionHub / DbConnectionHubScoped service that manages database connections and controls their lifecycle, including opening, closing, and resource disposal.
IDbSession / DbSessionRepresents a database session that allows performing query, execution, and transaction operations using Dapper as the underlying engine.
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();
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;
}
}
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
}
);
}
}
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;
}
}
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();
QueryAsync<T>() - Returns multiple results as IEnumerable<T>QueryFromRoutineAsync<T>() - Returns multiple results from routine as IEnumerable<T>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 valueQuerySingleAsync<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 valueQueryMultipleAsync() - Returns multiple result sets in a single queryQueryMultipleFromRoutineAsync() - Returns multiple result sets from routineExecuteAsync() - Executes SQL statement (INSERT, UPDATE, DELETE) and returns affected rowsExecuteRoutineAsync() - Executes stored procedure or function and returns affected rowsExecuteScriptAsync() - Executes SQL script from file or folderBeginTransaction() - Starts a transactionCommitTransactionAsync() - Commits the current transactionRollbackTransactionAsync() - Rolls back the current transactionAll Dapper wrapper methods accept the following parameters:
string statement or string 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.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 net8.0 is compatible. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 was computed. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
This package is not used by any NuGet packages.
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 5.0.0 | 92 | 6/8/2026 |
| 4.0.4 | 209 | 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 |