Skip to content

Commit a8aa6a4

Browse files
authored
Merge pull request #14 from Clifftech123/develop
docs: update CHANGELOG with detailed project features and enhancements
2 parents 1ebcef3 + 78dad7f commit a8aa6a4

1 file changed

Lines changed: 105 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,106 @@
1+
# Changelog
12

3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
---
9+
10+
## [1.0.0] - 2026-04-09
11+
12+
### Added
13+
14+
#### Base Entity Hierarchy
15+
- `BaseEntity<TKey>` / `BaseEntity` — strongly-typed primary key base class
16+
- `AuditableEntity<TKey>` / `AuditableEntity` — adds `CreatedAt`, `CreatedBy`, `UpdatedAt`, `UpdatedBy`
17+
- `SoftDeletableEntity<TKey>` / `SoftDeletableEntity` — adds `IsDeleted`, `DeletedAt`, `DeletedBy`
18+
- `FullEntity<TKey>` / `FullEntity` — soft-delete + audit + optimistic concurrency (`RowVersion`)
19+
20+
#### Entity Configuration Bases
21+
- `BaseEntityConfiguration<TEntity, TKey>` — auto-configures primary key
22+
- `AuditableEntityConfiguration<TEntity, TKey>` — adds audit columns and `CreatedAt` index
23+
- `SoftDeletableEntityConfiguration<TEntity, TKey>` — adds `IsDeleted` default and composite index
24+
25+
#### Interfaces
26+
- `IAuditable` — audit timestamp contract
27+
- `IFullAuditable` — field-level change history contract
28+
- `ISoftDeletable` — soft delete contract
29+
- `IConcurrencyAware` — optimistic concurrency contract
30+
- `IUserProvider` — current user resolution contract
31+
- `IRepository<T>` / `IReadRepository<T>` — repository contracts
32+
- `IUnitOfWork` — unit of work contract
33+
- `ISpecification<T>` / `ISpecification<T, TResult>` — specification pattern contracts
34+
35+
#### Soft Delete
36+
- `SoftDeleteInterceptor` — intercepts `DELETE` and converts to `UPDATE SET IsDeleted = true`
37+
- Global query filter automatically excludes soft-deleted rows
38+
- `IncludeDeleted()` — bypass the filter to include soft-deleted rows
39+
- `OnlyDeleted()` — query only soft-deleted rows
40+
- `GetDeletedAsync()` — load all soft-deleted rows from a `DbSet<T>`
41+
- `Restore()` — clear soft-delete flags on an entity
42+
- `HardDelete()` — permanently remove a record bypassing the interceptor
43+
- Optional cascade soft delete for loaded navigation properties
44+
45+
#### Audit Trail
46+
- `AuditInterceptor` — auto-stamps `CreatedAt`/`CreatedBy` on insert and `UpdatedAt`/`UpdatedBy` on update
47+
- Protects `CreatedAt` and `CreatedBy` from being overwritten on update
48+
- Optional full audit log (`IFullAuditable`) — records every field change in an `AuditLog` table
49+
50+
#### Repository and Unit of Work
51+
- `Repository<T>` — generic implementation of `IRepository<T>` and `IReadRepository<T>`
52+
- `UnitOfWork<TContext>` — groups multiple repository operations into a single `SaveChangesAsync`
53+
- All registered automatically via `AddEfCoreExtensions`
54+
55+
#### Specification Pattern
56+
- `Specification<T>` base class with `AddCriteria`, `AddInclude`, `ApplyOrderBy`, `ApplyPaging`, `ApplyAsNoTracking`, `ApplyAsSplitQuery`
57+
- `Specification<T, TResult>` — projecting specification with `ApplySelector`
58+
- `And()` / `Or()` combinators — compose specifications at runtime
59+
- `SpecificationBuilder<T>` — fluent inline builder for one-off queries
60+
- `ApplySpecification` extension — apply any spec to an `IQueryable<T>`
61+
- `ToListAsync(ISpecification<T, TResult>)` — project and materialise in one call
62+
- `ToPagedFromSpecAsync` — apply spec criteria then paginate
63+
64+
#### Pagination
65+
- `ToPagedAsync` — offset pagination returning `PagedResult<T>` with full metadata
66+
- `SelectToPagedAsync` — project before materialising, then paginate
67+
- `ToKeysetPagedAsync` — keyset/cursor pagination returning `KeysetPagedResult<T>`
68+
- `PagedResult<T>.Map<TDestination>` — map items to a different type while preserving metadata
69+
70+
#### Dynamic Filters and Sorting
71+
- `ApplyFilters(FilterDescriptor[])` — apply runtime filter arrays to any `IQueryable<T>`
72+
- Supported operators: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, `contains`, `startswith`, `endswith`, `isnull`, `isnotnull`, `in`, `between`
73+
- `ApplySorts(SortDescriptor[])` — apply runtime multi-column sorting
74+
- Dot-separated nested property paths supported in both filters and sorts
75+
76+
#### Query Helpers
77+
- `GetByIdAsync` / `GetByIdOrThrowAsync` — single entity lookup by primary key
78+
- `GetByIdsAsync` — batch lookup translating to `WHERE key IN (...)`
79+
- `GetAllAsync` — load all rows from a `DbSet<T>`
80+
- `FindAsync` — load by predicate or specification
81+
- `ExistsAsync` — existence check by key or predicate
82+
- `WhereIf` / `WhereIfNotNull` / `WhereIfNotEmpty` — conditional filtering
83+
- `OrderByDynamic` / `ThenByDynamic` — sort by property name string
84+
- `SelectToListAsync` / `SelectFirstOrDefaultAsync` / `SelectDistinctAsync` — projection helpers
85+
- `WithNoTracking` — alias for `AsNoTracking`
86+
- `RemoveRangeAsync` — load and stage for deletion by predicate
87+
88+
#### DbContext Utilities
89+
- `ExecuteInTransactionAsync` — wraps work in a transaction respecting EF Core execution strategy
90+
- `DetachAll` — clears all tracked entities from the change tracker
91+
- `TruncateAsync<T>` — truncates a table by entity type using EF Core metadata
92+
93+
#### Slow Query Logging
94+
- `SlowQueryInterceptor` — logs a warning for any query exceeding a configurable threshold
95+
- Configured via `LogSlowQueries(TimeSpan threshold)`
96+
97+
#### Structured Exceptions
98+
- `EfCoreException` — abstract base for all EfCoreKit exceptions
99+
- `EntityNotFoundException` — thrown by `GetByIdOrThrowAsync` and `RemoveByIdAsync`
100+
- `ConcurrencyConflictException` — thrown automatically on stale row-version conflict
101+
- `DuplicateEntityException` — throw manually when catching unique constraint violations
102+
- `InvalidFilterException` — thrown by `ApplyFilters` for invalid filter descriptors
103+
104+
#### DI Registration
105+
- `AddEfCoreExtensions<TContext>` — single call registers DbContext, interceptors, repository, and unit of work
106+
- `EfCoreDbContext<TContext>` — optional base context that wires interceptors and query filters automatically

0 commit comments

Comments
 (0)