INTRODUCTION · CORE-DATAeQuantic.Core.DataeQuantic.Core.Data extends the core library with the abstractions data access needs: a unit of work, repositories, and the mapping between a stored row and a domain entity.
Overview
It implements unit of work, the repository pattern and object-relational mapping as one set, so a transaction spans several repositories and still commits once.It works across database providers and persistence strategies, and the choice of provider stays in configuration rather than in the code that queries.
Install it
shell
dotnet add package eQuantic.Core.Data
What it does
Unit of workOne transaction across several repositories, committed once, so a half-written change cannot survive an error.
Repositories, extendedGeneric repositories with specifications, sorting, paging and projections — the shape of the query arrives as an argument.
Entity mappingMapping between domain entities and DTOs, configured rather than assumed.
Auditing, on its ownCreation, change and deletion are tracked for you, on every entity that asks for it.
Multi-tenancyData isolated per tenant, with the filter applied for you instead of remembered at every call site.
Unit of workOne transaction across several repositories, committed once, so a half-written change cannot survive an error.
Repositories, extendedGeneric repositories with specifications, sorting, paging and projections — the shape of the query arrives as an argument.
Entity mappingMapping between domain entities and DTOs, configured rather than assumed.
Auditing, on its ownCreation, change and deletion are tracked for you, on every entity that asks for it.
Multi-tenancyData isolated per tenant, with the filter applied for you instead of remembered at every call site.
Quick start
Configure the context — Your data context inherits the base, which brings the auditing and the tenant filters with it.
C#
public class ApplicationDbContext : EQuanticDbContext{ public DbSet<Product> Products { get; set; } public DbSet<Order> Orders { get; set; } public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.ApplyConfigurationsFromAssembly(typeof(ApplicationDbContext).Assembly); }}
Coordinate with a unit of work — Take the interface, touch several repositories, and save once.
C#
public class OrderService{ private readonly IUnitOfWork _unitOfWork; public OrderService(IUnitOfWork unitOfWork) { _unitOfWork = unitOfWork; } public async Task<Order> CreateOrderAsync(CreateOrderRequest request) { var order = new Order(request.CustomerId, request.Items); await _unitOfWork.GetRepository<Order>().AddAsync(order); await _unitOfWork.GetRepository<Product>().UpdateStockAsync(request.Items); await _unitOfWork.SaveChangesAsync(); return order; }}
Query with specifications — Build the query as an object — combinable, testable, and reusable at the next call site.
C#
public class GetOrdersByCustomerSpec : Specification<Order>{ public GetOrdersByCustomerSpec(int customerId, DateTime? fromDate = null) { Criteria = o => o.CustomerId == customerId; if (fromDate.HasValue) Criteria = Criteria.And(o => o.CreatedAt >= fromDate.Value); AddInclude(o => o.Items); AddInclude("Items.Product"); ApplyOrderByDescending(o => o.CreatedAt); }}
Public surface
NAMESPACE
PUBLIC SURFACE
IUnitOfWork
Coordinates the transactions and the repositories taking part in them.
EQuanticDbContext
The base Entity Framework context, with the auditing and the tenant filter already in place.
Specification<T>
The base class for a composable query specification.
Prefer reading code?
Every package is MIT and public, and the samples are copy-paste ready.