EFAcceleratorTools 2.0.0
dotnet add package EFAcceleratorTools --version 2.0.0
NuGet\Install-Package EFAcceleratorTools -Version 2.0.0
<PackageReference Include="EFAcceleratorTools" Version="2.0.0" />
<PackageVersion Include="EFAcceleratorTools" Version="2.0.0" />
<PackageReference Include="EFAcceleratorTools" />
paket add EFAcceleratorTools --version 2.0.0
#r "nuget: EFAcceleratorTools, 2.0.0"
#:package EFAcceleratorTools@2.0.0
#addin nuget:?package=EFAcceleratorTools&version=2.0.0
#tool nuget:?package=EFAcceleratorTools&version=2.0.0
EFAcceleratorTools
π High-performance utilities to boost your Entity Framework Core experience.
Built for developers who need more power, flexibility, and speed when querying data.
EFAcceleratorTools is a .NET library designed to enhance productivity and performance when working with Entity Framework Core. It provides dynamic projection, advanced pagination, parallel query execution, simplified entity mapping, and a robust generic repository pattern β all with a lightweight and extensible design.
π License: MIT
β¨ Features
- π§ Dynamic Selects β Project typed objects based on property names.
- π Pagination Utilities β Effortless pagination helpers for IQueryable queries.
- π§΅ Parallel Query Execution β Process large query sets in parallel with ease.
- πΊοΈ Simplified Entity Mapping β Easily configure and manage entity mappings for your domain models.
- π¦ Generic Repository β Reusable, extensible repository pattern for CRUD operations and advanced queries.
- π§ Extensible & Lightweight β Designed to be modular and easy to integrate.
- More features coming soon!
π Getting Started
Install via NuGet:
dotnet add package EFAcceleratorTools --version 1.0.1
π οΈ 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 _context.Courses
.DynamicSelect(filters: default, orders: default, nameof(Course.Id), nameof(Course.Title))
.ToListAsync();
// And you can select complex properties, including collections
KeyOf<Course>[] 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 _context.Courses
.DynamicSelect(AllRelationships)
.ToListAsync();
Pagination
Effortlessly paginate your queries, with filtering and ordering capabilities:
var queryFilter = new QueryFilterBuilder<Course>(c => c.Id)
.WithPage(1)
.WithPageSize(100)
.WithFields(SelectsDefaults<Course>.BasicFields)
.Build();
var firstPage = await _context.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:
ParallelQueryExecutor.DoItParallelAsync
(
() => _dataContextFactory.CreateDbContext().Courses.OrderBy(x => x.Id).AsQueryable(),
new ParallelParams
{
TotalRegisters = _dataContext.Courses.Count(),
BatchSize = 1000,
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 DataContext _dataContext;
private readonly IDbContextFactory<DataContext> _dataContextFactory;
private readonly IApplicationLogger _logger;
public CourseRepository(DataContext context, IDbContextFactory<DataContext> dataContextFactory, IApplicationLogger logger) : base(context, new DbContextFactoryAdapter(dataContextFactory))
{
_dataContext = context;
_dataContextFactory = dataContextFactory;
_logger = logger;
}
}
...
var allCourses = await _courseRepository.GetAllAsync();
π Example Project
See the EFAcceleratorTools.Examples
project for a complete working example, including setup and advanced scenarios.
π€ Contributing
Contributions are welcome! Please open issues or submit pull requests for new features, bug fixes, or documentation improvements. Contributing guidelines are still under construction.
π License
This project is licensed under the MIT License.
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
- Apparatus.AOT.Reflection (>= 1.1.3)
- Microsoft.EntityFrameworkCore (>= 6.0.36)
-
net7.0
- Apparatus.AOT.Reflection (>= 1.1.3)
- Microsoft.EntityFrameworkCore (>= 7.0.20)
-
net8.0
- Apparatus.AOT.Reflection (>= 1.1.3)
- Microsoft.EntityFrameworkCore (>= 8.0.18)
-
net9.0
- Apparatus.AOT.Reflection (>= 1.1.3)
- Microsoft.EntityFrameworkCore (>= 9.0.8)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.