Release Notes
10.0.0
Targets .NET 10. Contains breaking changes.
Breaking Changes
Satellite packages folded into Albatross.EFCore
The Albatross.EFCore.Audit, Albatross.EFCore.ChangeReporting and Albatross.EFCore.AutoCacheEviction packages have been removed. Their functionality now lives in the core Albatross.EFCore package, reimplemented as EF Core SaveChangesInterceptor types instead of the old IDbEventHandler pipeline:
| Removed package | Replacement in Albatross.EFCore |
|---|---|
Albatross.EFCore.Audit |
ChangeAuditInterceptor<TChangeEntity, TEntityId, TActorId> |
Albatross.EFCore.ChangeReporting |
ChangeReportInterceptor<TEntity> |
Albatross.EFCore.AutoCacheEviction |
CacheEvictionInterceptor<T> |
Drop the package references and register the interceptors with DbContextOptionsBuilder.AddInterceptors instead.
The old change-reporting configuration surface is gone entirely — IChangeReport, the mutable ChangeReportingOptions class, ChangeReportBuilder<T> and all of its extension methods (ChangeType, FixedHeaders, IgnoreProperties, OnReportGenerated, Prefix, Postfix, Formatter, AsyncFormatter, Format, FormatFixedHeader, NumericFormat, DateFormat, TimeFormat, Deleted, Modified, Added, AllChangeTypes, ExcludeAuditProperties, ExcludeTemporalProperties). ChangeReportInterceptor<TEntity> is configured through required init properties (ChangeType, ShouldSkip, OnReportGenerated) instead.
The audit marker interfaces ICreatedBy, ICreatedUtc, IModifiedBy and IModifiedUtc have been removed. Auditing is now opt-in per entity by implementing IAuditable<TEntityId>.
Albatross.EFCore.CodeGen
The source generator has been rewritten as an incremental generator (IIncrementalGenerator). The previous EntityModelBuilderClassCodeGen and EntityModelClassWalker classes have been replaced by EntityModelBuilderClassCodeGenerator.
The generated CodeGenExtensions class is now emitted into <RootNamespace>.AutoGenerated, falling back to the assembly name. Previously the namespace was taken from whichever DbSession subclass the syntax provider happened to collect first, so a project with more than one session could see the class relocate between builds. Callers whose OnModelCreating is not already in <RootNamespace>.AutoGenerated now need a using for it.
Albatross.Testing.EFCore (removed)
The Albatross.Testing.EFCore package has been removed.
New Features
Albatross.EFCore.CodeAnalysis (new package)
A new Roslyn analyzer package shipping ALBEFCORE001 (MissingTransactionCommit, Usage, Warning). It warns when a transaction created via BeginTransactionAsync is never committed within the method that creates it. A commit is recognized as Commit()/CommitAsync(...) on the transaction, or passing the transaction to SaveAndCommitAsync(...). The search is scoped to the single method body by design.
Albatross.EFCore — Repository Pattern
A new IRepository interface and Repository<T> abstract base class have been added.
Add<T>,Delete<T>,Get<T>,GetRequired<T>andSaveChangesAsyncGetRequired<T>throwsNotFoundException<T>when the key is not foundSaveChangesAsyncconverts constraint violations into semantic exceptions viaISemanticExceptionConverterBeginTransactionAsyncandSaveAndCommitAsyncown the transaction boundary;SaveAndCommitAsyncflushes the change tracker before committing, sinceCommitAsyncalone does not and would otherwise silently drop tracked mutationsRepository<T>accepts anISemanticExceptionConverterfor database-specific exception translation
Albatross.EFCore — Change Auditing
ChangeAuditInterceptor<TChangeEntity, TEntityId, TActorId> writes a Change<TEntityId, TActorId> record for every IAuditable<TEntityId> entity modified or deleted in the same transaction. Added entities are intentionally excluded. Changed values are stored as a JSON snapshot; concurrency tokens are skipped.
IAuditable<TEntityId> exposes MaskedProperties and IgnoredProperties. Ignored properties are omitted from the snapshot entirely; masked properties are recorded as ***, proving a change occurred without leaking the value. Both have default implementations returning an empty collection.
Requires IGetCurrentActorId<T> and TimeProvider in DI.
Albatross.EFCore.SqlServer — Constraint Violation Helpers
Two extension methods on Exception have been added:
IsUniqueConstraintViolation()— detects SQL errors 2601 and 2627IsForeignKeyConstraintViolation()— detects SQL error 547
Albatross.EFCore.PostgreSQL — Constraint Violation Helpers
Two extension methods on Exception have been added:
IsUniqueConstraintViolation()— detectsSqlState23505IsForeignKeyConstraintViolation()— detectsSqlState23503
Semantic exception converters preserve the original exception
EFCoreSemanticExceptionConverter, SqlServerSemanticExceptionConverter and PostgresSemanticExceptionConverter now pass the source exception to ConflictException, NotFoundException and PreconditionFailedException, so the provider exception survives as InnerException.
8.1.2
- Documentation updates
- Minor internal fixes