Dot.Conductor
1.3.0
dotnet add package Dot.Conductor --version 1.3.0
NuGet\Install-Package Dot.Conductor -Version 1.3.0
<PackageReference Include="Dot.Conductor" Version="1.3.0" />
paket add Dot.Conductor --version 1.3.0
#r "nuget: Dot.Conductor, 1.3.0"
// Install Dot.Conductor as a Cake Addin #addin nuget:?package=Dot.Conductor&version=1.3.0 // Install Dot.Conductor as a Cake Tool #tool nuget:?package=Dot.Conductor&version=1.3.0
Unit of Work and Repository Pattern with Entity Framework Core
This library provides an implementation of the Unit of Work (UoW) and Repository pattern using Entity Framework (EF) Core, with support for multi-tenancy.
Features
- Unit of Work pattern implementation
- Generic Repository pattern
- Multi-tenancy support
- Customizable database context configuration
- Paged results for efficient data retrieval
- Transaction management
- Stored procedures support
Setting Up
Basic Setup
In your Startup.cs
or Program.cs
(for .NET 6+), register the UnitOfWork and repositories using the provided
extension method:
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddUnitOfWorkAndRepositories<MyDbContext>(
Configuration.GetConnectionString("DefaultConnection"),
sqlOptions => {
// Configure SQL options if needed
},
isDevelopment: Environment.IsDevelopment()
);
// ...
}
Multi-tenant Setup
For multi-tenant applications, use the following setup:
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddMultiTenantUnitOfWorkAndRepositories<MyDbContext>(
sqlOptions => {
// Configure SQL options if needed
},
isDevelopment: Environment.IsDevelopment()
);
// Register your tenant strategy
services.AddScoped<ITenantStrategy, YourTenantStrategyImplementation>();
// ...
}
Make sure to implement the ITenantStrategy
interface to provide tenant-specific connection strings:
public class YourTenantStrategyImplementation : ITenantStrategy
{
public Task<string> GetTenantIdentifierAsync()
{
// Implement logic to get the current tenant identifier
}
public Task<string> GetConnectionStringAsync(string tenantIdentifier)
{
// Implement logic to get the connection string for the given tenant
}
}
Using Unit of Work
In Controllers or Services
Inject IUnitOfWork<MyDbContext>
in your controller or service constructor:
public class UserController : ControllerBase
{
private readonly IUnitOfWork<MyDbContext> _unitOfWork;
public UserController(IUnitOfWork<MyDbContext> unitOfWork)
{
_unitOfWork = unitOfWork;
}
// ...
}
Querying Data
public async Task<IActionResult> GetUser(int id)
{
var userRepository = _unitOfWork.GetRepository<User>();
var user = await userRepository.GetByIdAsync(id);
if (user == null)
{
return NotFound();
}
return Ok(user);
}
Modifying Data
public async Task<IActionResult> UpdateUser(User user)
{
var userRepository = _unitOfWork.GetRepository<User>();
await userRepository.UpdateAsync(user);
await _unitOfWork.CommitAsync();
return Ok(user);
}
Using Transactions
public async Task<IActionResult> TransferFunds(int fromUserId, int toUserId, decimal amount)
{
try
{
await _unitOfWork.BeginTransactionAsync();
var userRepository = _unitOfWork.GetRepository<User>();
var fromUser = await userRepository.GetByIdAsync(fromUserId);
var toUser = await userRepository.GetByIdAsync(toUserId);
fromUser.Balance -= amount;
toUser.Balance += amount;
await userRepository.UpdateAsync(fromUser);
await userRepository.UpdateAsync(toUser);
await _unitOfWork.CommitTransactionAsync();
return Ok("Transfer successful");
}
catch (Exception)
{
await _unitOfWork.RollbackTransactionAsync();
return BadRequest("Transfer failed");
}
}
Paged Results
public async Task<IActionResult> GetUsers(int pageNumber, int pageSize)
{
var userRepository = _unitOfWork.GetRepository<User>();
var pagedUsers = await userRepository.GetPagedDataAsync(
pageNumber,
pageSize,
u => u.LastName
);
return Ok(pagedUsers);
}
Using Unit of Work Outside of Scope
To use UnitOfWork outside of the default scope, use the extension method provided for IServiceScopeFactory
:
public async Task<bool> PerformUnitOfWorkAsync(IServiceScopeFactory scopeFactory)
{
var result = await scopeFactory.UseUnitOfWork<MyDbContext, bool>("YourConnectionString", async uow =>
{
var userRepository = uow.GetRepository<User>();
var user = new User { Name = "John Doe", Email = "john@example.com" };
await userRepository.AddAsync(user);
await uow.CommitAsync();
return true;
});
return result;
}
Notes
- The implementation handles proper disposal of resources and manages the lifecycle of the DbContext.
- For multi-tenant scenarios, ensure that your
ITenantStrategy
implementation correctly identifies tenants and provides the appropriate connection strings. - The library includes support for stored procedures through the
GetStoredProcedures<TProcedures>()
method, but you need to implement the procedures class yourself. - In development mode, the library enables sensitive data logging, detailed errors, and console logging for the DbContext.
Contributing
Contributions to improve the library are welcome. Please submit issues and pull requests on the project's repository.
License
MIT License
Copyright (c) [2024] [Nathan WILCKÉ]
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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. |
-
net8.0
- Microsoft.EntityFrameworkCore (>= 8.0.0)
- Microsoft.EntityFrameworkCore.SqlServer (>= 8.0.0)
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.3.0 | 355 | 6/23/2024 |
1.2.23 | 327 | 3/11/2024 |
1.2.22 | 322 | 12/29/2023 |
1.2.21 | 117 | 12/29/2023 |
1.2.20 | 120 | 12/28/2023 |
1.2.19 | 122 | 12/19/2023 |
1.2.18 | 87 | 12/19/2023 |
1.2.17 | 89 | 12/19/2023 |
1.2.16 | 238 | 11/15/2023 |
1.2.15 | 134 | 11/5/2023 |
1.2.14 | 112 | 11/4/2023 |
1.2.13 | 98 | 11/4/2023 |
1.2.12 | 93 | 11/4/2023 |
1.2.11 | 98 | 11/4/2023 |
1.2.10 | 104 | 11/4/2023 |
1.2.9 | 106 | 11/4/2023 |
1.2.8 | 117 | 11/4/2023 |
1.2.7 | 106 | 11/2/2023 |
1.2.6 | 100 | 11/2/2023 |
1.2.5 | 125 | 11/2/2023 |
1.2.4 | 114 | 11/2/2023 |
1.2.3 | 113 | 11/1/2023 |
1.2.2 | 105 | 11/1/2023 |
1.2.1 | 116 | 10/27/2023 |
1.2.0 | 113 | 10/27/2023 |
1.1.1 | 104 | 10/25/2023 |
1.1.0 | 113 | 10/19/2023 |