CleanArchAcceleratorTools.Infrastructure
1.0.1
dotnet add package CleanArchAcceleratorTools.Infrastructure --version 1.0.1
NuGet\Install-Package CleanArchAcceleratorTools.Infrastructure -Version 1.0.1
<PackageReference Include="CleanArchAcceleratorTools.Infrastructure" Version="1.0.1" />
<PackageVersion Include="CleanArchAcceleratorTools.Infrastructure" Version="1.0.1" />
<PackageReference Include="CleanArchAcceleratorTools.Infrastructure" />
paket add CleanArchAcceleratorTools.Infrastructure --version 1.0.1
#r "nuget: CleanArchAcceleratorTools.Infrastructure, 1.0.1"
#:package CleanArchAcceleratorTools.Infrastructure@1.0.1
#addin nuget:?package=CleanArchAcceleratorTools.Infrastructure&version=1.0.1
#tool nuget:?package=CleanArchAcceleratorTools.Infrastructure&version=1.0.1
CleanArchAcceleratorTools.Infrastructure
This module is part of CleanArchAcceleratorTools, a toolkit to accelerate building applications with Clean Architecture. It implements the Infrastructure layer.
Related modules:
- CleanArchAcceleratorTools.Controller
- CleanArchAcceleratorTools.Application
- CleanArchAcceleratorTools.Domain
- CleanArchAcceleratorTools.AllInOne
📄 License: MIT
🧠 Principles
🔗 Role in the architecture
- Controller: Exposes endpoints, it does not contain business rules.
- Application: Orchestrates use cases and references the Domain and repository.
- Domain: Pure domain with business rules and validations.
- Infrastructure: Implements persistence/mapping for Domain entities.
- Mediator: Handles commands, queries, and notifications.
✨ Features
- Dynamic Selects – Project typed objects based on property names.
- Dynamic Filtering – Filter queries with a fluent builder using clauses and operators.
- Dynamic Sort – Sort queries with multiple fields and directions.
- Pagination Utilities – Helpers for
IQueryableincluding filtering and ordering. - Parallel Query Execution – Process large query sets in parallel.
- Simplified Entity Mapping – Configure and register mappings for domain models.
- Generic Repository – Reusable repository pattern for CRUD and advanced queries.
- DataTable Creation – Build
DataTablefrom lists for procedures and raw SQL. - Extensible & Lightweight – Modular, discoverable, and easy to integrate.
🧩 Compatibility
Multi-target:
- .NET 6
- .NET 7
- .NET 8
- .NET 9
Use an EF Core version compatible with your target framework.
✅ Prerequisites
- EF Core 6+ (match your framework)
- A configured
DbContext - Optional:
Newtonsoft.JsonorSystem.Text.Jsonfor serialization scenarios
🚀 Installation
dotnet add package CleanArchAcceleratorTools.Infrastructure --version 1.0.0
⚡ Quickstart
- If you have separated Application project add this module reference on it. Add allInOne if using a single project.
- Register your
DbContextin DI.builder.Services.AddDbContext<YourContext>(); builder.Services.AddDbContextFactory<YourContext, YourContextFactory>(); - Configure the generic DbContext DI and CleaArch services
builder.Services.AddScoped<DbContext>(sp => sp.GetRequiredService<YourContext>()); builder.Services.AddScoped<IDbContextFactory<DbContext>>(sp => new DbContextFactoryAdapter(sp.GetRequiredService<IDbContextFactory<YourContext>>())); builder.Services.AddCleanArchConfiguration<YourContext>(); - Create your models as needed. Needed to Inherit from a base
Entityif you want to use common properties. - (Optional) Map your entities using
EntityTypeConfiguration<T>as the usage example below. - (Optional) Create your repositories extending
IGenericRepository<T>andGenericRepository<T>as example below. - Use the features provided.
🛠️ Usage Examples
Dynamic Select
Tired of Include and ThenInclude everything? With DynamicSelect, you can easily project only the properties you need, without the overhead of loading entire entities and without having to make the Select manually each time.
You can simply add the fields you want for each relationship and the library will handle the rest. It supports simple properties and nested complex relationships, including Collections.
It includes filtering and ordering capabilities too.
Bonus Tip: Enable NullValueHandling = NullValueHandling.Ignore in Newtonsoft.Json serialization or similars to have a GraphQL like solution for your REST APIs.
You can select simple properties of the entity
var courses = await _yourContext.Courses
.DynamicSelect(nameof(Course.Id), nameof(Course.Title))
.ToListAsync();
Or you can select complex properties, including collections
string[] AllRelationships =
[
string.Format("{0}", nameof(Course.Id)),
string.Format("{0}", nameof(Course.InstructorId)),
string.Format("{0}", nameof(Course.Title)),
string.Format("{0}", nameof(Course.CreatedAt)),
string.Format("{0}.{1}", nameof(Course.Instructor), nameof(Course.Instructor.Id)),
string.Format("{0}.{1}", nameof(Course.Instructor), nameof(Course.Instructor.FullName)),
string.Format("{0}.{1}", nameof(Course.Instructor), nameof(Course.Instructor.CreatedAt)),
string.Format("{0}.{1}.{2}", nameof(Course.Instructor), nameof(Instructor.Profile), nameof(Profile.Id)),
string.Format("{0}.{1}.{2}", nameof(Course.Instructor), nameof(Instructor.Profile), nameof(Profile.InstructorId)),
string.Format("{0}.{1}.{2}", nameof(Course.Instructor), nameof(Instructor.Profile), nameof(Profile.Bio)),
string.Format("{0}.{1}.{2}", nameof(Course.Instructor), nameof(Instructor.Profile), nameof(Profile.LinkedInUrl)),
string.Format("{0}.{1}.{2}", nameof(Course.Instructor), nameof(Instructor.Profile), nameof(Profile.CreatedAt)),
string.Format("{0}.{1}", nameof(Course.Modules), nameof(Module.Id)),
string.Format("{0}.{1}", nameof(Course.Modules), nameof(Module.CourseId)),
string.Format("{0}.{1}", nameof(Course.Modules), nameof(Module.Name)),
string.Format("{0}.{1}", nameof(Course.Modules), nameof(Module.CreatedAt)),
string.Format("{0}.{1}.{2}", nameof(Course.Modules), nameof(Module.Lessons), nameof(Lesson.Id)),
string.Format("{0}.{1}.{2}", nameof(Course.Modules), nameof(Module.Lessons), nameof(Lesson.ModuleId)),
string.Format("{0}.{1}.{2}", nameof(Course.Modules), nameof(Module.Lessons), nameof(Lesson.Title)),
string.Format("{0}.{1}.{2}", nameof(Course.Modules), nameof(Module.Lessons), nameof(Lesson.Duration)),
string.Format("{0}.{1}.{2}", nameof(Course.Modules), nameof(Module.Lessons), nameof(Lesson.CreatedAt))
];
var courses = await _yourContext.Courses
.DynamicSelect(AllRelationships)
.ToListAsync();
You can filter and sort as well
var dynamicFilter = ...;
var dynamicSort = ...;
// populate dynamicFilter and dynamicSort with Set properties or Builder...
var courses = await _yourContext.Courses
.DynamicSelect(nameof(Course.Id), nameof(Course.Title))
.Where(dynamicFilter.CompileFilter())
.OrderBy(dynamicSort.CompileSort().First().Expression)
.ToListAsync();
Pagination
Effortlessly paginate your queries, with dynamic filtering and dynamic ordering capabilities:
var dynamicFilter = ...;
var dynamicSort = ...;
// populate dynamicFilter and dynamicSort with Set properties or Builder...
var queryFilter = new QueryFilterBuilder<Course>()
.WithPage(1)
.WithPageSize(100)
.WithDynamicFilter(dynamicFilter)
.WithDynamicSort(dynamicSort)
.WithFields(SelectsDefaults<Course>.BasicFields)
.Build();
var firstPage = await _yourContext.Courses
.OrderBy(x => x.Id)
.GetPagination(queryFilter)
.ToPaginationResultListAsync();
Entity Mapping
Map your entities with ease:
public class CourseMap : EntityTypeConfiguration<Course>
{
public override void Map(EntityTypeBuilder<Course> builder)
{
builder.ToTable("TB_COURSE");
builder.HasKey(x => x.Id)
.HasName("SQ_COURSE");
builder.Property(x => x.Id)
.HasColumnName("SQ_COURSE")
.HasColumnType("bigint")
.UseIdentityColumn();
builder.Property(x => x.InstructorId)
.HasColumnName("SQ_INSTRUCTOR")
.HasColumnType("bigint");
builder.Property(x => x.Title)
.HasColumnName("TX_TITLE")
.HasColumnType("nvarchar(100)");
builder.Property(x => x.CreatedAt)
.HasColumnName("DT_CREATION")
.HasColumnType("nvarchar(100)");
}
}
...
public static class MappingsHolder
{
public static Dictionary<Type, IEntityTypeConfiguration> GetMappings()
{
var mappings = new Dictionary<Type, IEntityTypeConfiguration>();
mappings.Add(typeof(Course), new CourseMap());
return mappings;
}
}
...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.RegisterModelsMapping(MappingsHolder.GetMappings());
}
Parallel Query Execution
Execute queries in parallel to improve performance on large datasets:
await ParallelQueryExecutor.DoItParallelAsync
(
() => _registeredContextFactory.Create(Guid.NewGuid().ToString()).Courses.OrderBy(x => x.Id).AsQueryable(),
new ParallelParams
{
TotalRegisters = _yourContext.Courses.Count(),
BatchSize = 10,
MaximumDegreeOfParalelism = Environment.ProcessorCount,
MaxDegreeOfProcessesPerThread = 1
},
_logger
);
Generic Repository
Leverage a robust, reusable repository for your entities:
public interface ICourseRepository : IGenericRepository<Course> { }
public class CourseRepository : GenericRepository<Course>, ICourseRepository
{
private readonly YourContext _yourContext;
private readonly IDbContextRegistratorService<YourContext> _registeredContextFactory;
private readonly IApplicationLogger _logger;
public CourseRepository(
YourContext context,
IDbContextRegistratorService<YourContext> registeredContextFactory,
IApplicationLogger logger
) : base(context, new DbContextRegistratorServiceAdapter(registeredContextFactory))
{
_yourContext = context;
_registeredContextFactory = registeredContextFactory;
_logger = logger;
}
}
...
// Usage
var allCourses = await _courseRepository.GetAllAsync();
DataTable Creation
Easily create DataTables, from Lists, for use in stored procedures and raw SQL queries:
var columnsOrder = new Dictionary<string, int>()
{
{ "Id", 0 },
{ "InstructorId", 1 },
{ "Title", 2 }
};
var courses = await _courseRepository.GetAllAsync();
var dataTable = courses.ToDataTable(columnsOrder, context);
Obs: The list type must be mapped in the context!
📚 Example Project
See the - CleanArchAcceleratorTools.Examples project for a complete working example, including setup and advanced scenarios. It implements a fully working API with all other modules implemented.
🧠 Tips
- Prefer
DynamicSelectto reduce materialization and network payloads. - Tune
ParallelParams(BatchSize,MaximumDegreeOfParalelism) per environment and workload. - Keep entity maps consistent and centralized via
MappingsHolderfor discoverability. - Centralize selection fields in a constant for reuse as in CourseSelects.
🤝 Contributing
Contributions are welcome! Open issues or submit PRs for features, bug fixes, or documentation improvements. Contributing guidelines are under construction.
| Product | Versions 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 is compatible. 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 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 is compatible. 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 was computed. 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. |
-
net6.0
- CleanArchAcceleratorTools.Domain (>= 1.0.1)
- Mapster (>= 7.4.0)
- Microsoft.EntityFrameworkCore (>= 6.0.36)
- Microsoft.EntityFrameworkCore.Relational (>= 6.0.36)
-
net7.0
- CleanArchAcceleratorTools.Domain (>= 1.0.1)
- Mapster (>= 7.4.0)
- Microsoft.EntityFrameworkCore (>= 7.0.20)
- Microsoft.EntityFrameworkCore.Relational (>= 7.0.20)
-
net8.0
- CleanArchAcceleratorTools.Domain (>= 1.0.1)
- Mapster (>= 7.4.0)
- Microsoft.EntityFrameworkCore (>= 8.0.18)
- Microsoft.EntityFrameworkCore.Relational (>= 8.0.18)
-
net9.0
- CleanArchAcceleratorTools.Domain (>= 1.0.1)
- Mapster (>= 7.4.0)
- Microsoft.EntityFrameworkCore (>= 9.0.8)
- Microsoft.EntityFrameworkCore.Relational (>= 9.0.8)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on CleanArchAcceleratorTools.Infrastructure:
| Package | Downloads |
|---|---|
|
CleanArchAcceleratorTools.Application
This module is part of CleanArchAcceleratorTools, a toolkit to accelerate building applications with Clean Architecture. |
|
|
CleanArchAcceleratorTools.AllInOne
This module is part of CleanArchAcceleratorTools, a toolkit to accelerate building applications with Clean Architecture. |
GitHub repositories
This package is not used by any popular GitHub repositories.