Flowsy.Db.Sql
0.4.0
See the version list below for details.
dotnet add package Flowsy.Db.Sql --version 0.4.0
NuGet\Install-Package Flowsy.Db.Sql -Version 0.4.0
<PackageReference Include="Flowsy.Db.Sql" Version="0.4.0" />
paket add Flowsy.Db.Sql --version 0.4.0
#r "nuget: Flowsy.Db.Sql, 0.4.0"
// Install Flowsy.Db.Sql as a Cake Addin #addin nuget:?package=Flowsy.Db.Sql&version=0.4.0 // Install Flowsy.Db.Sql as a Cake Tool #tool nuget:?package=Flowsy.Db.Sql&version=0.4.0
Flowsy Db Sql
This package includes implementations for interfaces defined in Flows.Db.Abstractions oriented to SQL databases.
Connection Factory
The class DbConnectionFactory implements the interface IDbConnectionFactory to create IDbConnection objects from a list of registered configurations identified by unique keys.
Repositories
The class DbRepository offers the foundation to implement the repository pattern.
Let's create an interface for a fictitious user repository:
public interface IUserRepository
{
Task<User?> GetByIdAsync(Guid userId, CancellationToken cancellationToken);
Task<User?> GetByEmailAsync(string email, CancellationToken cancellationToken);
}
Now we need to implement our interface:
public class UserRepository : DbRepository, IUserRepository
{
public UserRepository(IDbConnectionFactory connectionFactory, DbExceptionHandler? exceptionHandler = null)
: base(connectionFactory, exceptionHandler)
{
}
public UserRepository(IDbConnection connection, DbExceptionHandler? exceptionHandler = null)
: base(connection, exceptionHandler)
{
}
public UserRepository(IDbTransaction transaction, DbExceptionHandler? exceptionHandler = null)
: base(transaction, exceptionHandler)
{
}
public Task<User?> GetByIdAsync(Guid userId, CancellationToken cancellationToken)
{
// Invoke a stored routine: user_get_by_id(uuid)
return GetSingleOrDefaultAsync<User>(
"user_get_by_id",
new
{
UserId = userId
},
cancellationToken
);
}
public Task<User?> GetByEmailAsync(string email, CancellationToken cancellationToken)
{
// Invoke a stored routine: user_get_by_email(varchar)
return GetSingleOrDefaultAsync<User>(
"user_get_by_email",
new
{
Email = email
},
cancellationToken
);
}
}
By inheriting from DbRepository we can reuse its methods to execute SQL statements and routines without writing many lines of boilerplate code.
Repositories & Dependency Injection
var builder = WebApplication.CreateBuilder(args);
// Register a DbConnectionFactory service with the required configurations taken from the application settings
builder.Services.AddDbConnectionFactory(serviceProvider =>
{
var configuration = serviceProvider.GetRequiredService<IConfiguration>();
var sqlConfiguration = configuration.GetRequiredSection("Databases");
var dbConnectionConfigurations =
sqlConfiguration.GetChildren().Select(databaseConfiguration => new DbConnectionConfiguration
{
Key = databaseConfiguration.Key,
ProviderInvariantName = databaseConfiguration["ProviderInvariantName"],
ConnectionString = databaseConfiguration["ConnectionString"]
});
return new DbConnectionFactory(dbConnectionConfigurations.ToArray());
});
// Register repositories and configure their options
builder.Services
.AddRepositories(options =>
{
// Configure default options for all repository types.
// All settings are optional, they have default values to use if a custom value is not set.
options.ConnectionKey = "Default";
options.Schema = "public";
options.Conventions.DateTimeOffsetFormat = DbDateTimeOffsetFormat.Utc;
options.Conventions.Routines.DefaultType = DbRoutineType.StoredFunction;
options.Conventions.Routines.Prefix = "sf_";
options.Conventions.Routines.Casing = CaseConvention.LowerSnakeCase;
options.Conventions.Parameters.Prefix = "p_";
options.Conventions.Parameters.FormatPlaceholder = (_, routineType, parameterName, _) =>
{
return routineType switch
{
DbRoutineType.StoredFunction => $"{parameterName} => @{parameterName}",
_ => $"@{parameterName}"
};
};
options.Conventions.Enums.ValueFormat = DbEnumFormat.Name;
})
.Using<IUserRepository, UserRepository>(options =>
{
options.Schema = "auth";
})
.WithColumnMapping(
CaseConvention.LowerSnakeCase, // Database column names in lower_snake_case
t => typeof(IEntity).IsAssignableFrom(t), // Apply this column mapping to entities implementing the fictitious IEntity interface
Assembly.GetExecutingAssembly() // Scan types from the executing assembly
)
.WithTypeHandler(new DbDateOnlyTypeHandler()) // The fictitious DbDateOnlyTypeHandler must inherit from DbTypeHandler
;
Unit Of Work
The class DbUnitOfWork implements the interface IUnitOfWork to create IDbTransaction objects from a given IDbConnection.
For example, to create an invoice, we may need to create two kinds of entities:
- Invoice
- InvoiceId
- CustomerId
- CreateDate
- Total
- Taxes
- GrandTotal
- InvoiceItem
- InvoiceItemId
- InvoiceId
- ProductId
- Quantity
- Amount
A way of completing such operation from an application-level command handler could be:
public interface ISalesUnitOfWork : IUnitOfWork
{
IInvoiceRepository InvoiceRepository { get; }
IInvoiceItemRepository InvoiceItemRepository { get; }
}
public class SalesUnitOfWork : DbUnitOfWork, ISalesUnitOfWork
{
private readonly IInvoiceRepository? _invoiceRepository;
private readonly IInvoiceItemRepository? _invoiceItemRepository;
public SalesUnitOfWork(IDbConnection connection) : base(connection)
{
}
public IInvoiceRepository InvoiceRepository
=> _invoiceRepository ??= new InvoiceRepository(Transaction);
public IInvoiceItemRepository InvoiceItemRepository
=> _invoiceItemRepository ??= new InvoiceItemRepository(Transaction);
}
public class CreateInvoiceCommandHandler
{
private readonly IUnitOfWorkFactory _unitOfWorkFactory;
public CreateInvoiceCommandHandler(IUnitOfWorkFactory unitOfWorkFactory)
{
_unitOfWorkFactory = unitOfWorkFactory;
}
public async Task<CreateInvoiceCommandResult> HandleAsync(CreateInvoiceCommand command, CancellationToken cancellationToken)
{
// Begin operation
// IUnitOfWork inherits from IDisposable and IAsyncDisposable, if any exception is thrown, the current operation shall be rolled back
await using var unitOfWork = _unitOfWorkFactory.Create<ISalesUnitOfWork>();
var invoice = new Invoice();
// Populate invoice object from properties of command object
// Create the Invoice entity
var invoiceId = await unitOfWork.InvoiceRepository.CreateAsync(invoice, cancellationToken);
// Create all the InvoiceItem entities
foreach (var item in command.Items)
{
var invoiceItem = new InvoiceItem();
// Populate invoiceItem object from properties of item object
// Create each InvoiceItem entity
await unitOfWork.InvoiceItemRepository.CreateAsync(invoiceItem, cancellationToken);
}
// Commit the current operation
await unitOfWork.SaveAsync(cancellationToken);
// Return the result of the operation
return new CreateInvoiceCommandResult
{
InvoiceId = invoiceId
};
}
}
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. 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 Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.1 is compatible. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- Dapper (>= 2.1.15)
- Flowsy.Core (>= 4.0.0)
- Flowsy.Db.Abstractions (>= 0.1.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 7.0.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Flowsy.Db.Sql:
Package | Downloads |
---|---|
Flowsy.Db.Cli
Utility classes to create an interactive command line interface tool to perform database management tasks. |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
4.2.0 | 136 | 5/26/2024 |
4.1.0 | 116 | 5/25/2024 |
4.0.1 | 132 | 2/25/2024 |
4.0.0 | 119 | 2/10/2024 |
3.0.1 | 139 | 2/3/2024 |
3.0.0 | 108 | 2/3/2024 |
2.0.1 | 110 | 1/28/2024 |
2.0.0 | 99 | 1/27/2024 |
1.3.0 | 97 | 1/27/2024 |
1.2.0 | 129 | 1/15/2024 |
1.1.0 | 144 | 1/6/2024 |
1.0.0 | 199 | 12/11/2023 |
0.8.0 | 150 | 11/29/2023 |
0.7.0 | 213 | 11/27/2023 |
0.6.1 | 168 | 11/27/2023 |
0.6.0 | 167 | 11/27/2023 |
0.5.1 | 144 | 11/26/2023 |
0.5.0 | 123 | 11/26/2023 |
0.4.3 | 139 | 11/10/2023 |
0.4.2 | 124 | 11/10/2023 |
0.4.1 | 129 | 11/10/2023 |
0.4.0 | 125 | 11/10/2023 |
0.3.0 | 131 | 11/10/2023 |
0.2.0 | 141 | 10/24/2023 |
0.1.0 | 131 | 10/24/2023 |