11using EfCoreKit . Abstractions . Interfaces ;
2+ using EfCoreKit . Core . Filters ;
3+ using EfCoreKit . Core . Interceptors ;
24using Microsoft . EntityFrameworkCore ;
5+ using Microsoft . Extensions . Logging ;
36
47namespace EfCoreKit . Core . Context ;
58
69/// <summary>
710/// Base <see cref="DbContext"/> that provides automatic soft delete, audit trail,
8- /// multi-tenancy, and bulk operation support.
11+ /// multi-tenancy, and bulk operation support via EF Core interceptors .
912/// </summary>
13+ /// <remarks>
14+ /// This class inherits from <see cref="DbContext"/> — all standard EF Core features remain
15+ /// fully available. You can use LINQ queries, raw SQL (<c>Database.ExecuteSqlAsync</c>),
16+ /// change tracking, migrations, <c>DbSet<T></c>, and any EF Core provider feature
17+ /// exactly as you would with a plain <see cref="DbContext"/>.
18+ ///
19+ /// Save-pipeline behaviour (audit, soft delete, tenant enforcement) is handled by
20+ /// dedicated <see cref="Microsoft.EntityFrameworkCore.Diagnostics.SaveChangesInterceptor"/>
21+ /// instances registered in <see cref="OnConfiguring"/>. This means the same interceptors
22+ /// can be used with any <see cref="DbContext"/> — inheriting from this class is optional.
23+ /// </remarks>
1024/// <typeparam name="TContext">The derived context type.</typeparam>
1125public abstract class EfCoreKitDbContext < TContext > : DbContext
1226 where TContext : DbContext
1327{
1428 private readonly EfCoreKitOptions _options ;
1529 private readonly IUserProvider ? _userProvider ;
1630 private readonly ITenantProvider ? _tenantProvider ;
31+ private readonly ILoggerFactory ? _loggerFactory ;
1732
1833 /// <summary>
1934 /// Initializes a new instance of the <see cref="EfCoreKitDbContext{TContext}"/> class.
@@ -36,16 +51,19 @@ protected EfCoreKitDbContext(
3651 /// <param name="kitOptions">The EfCoreKit configuration options.</param>
3752 /// <param name="userProvider">The user provider for audit trail.</param>
3853 /// <param name="tenantProvider">The tenant provider for multi-tenancy.</param>
54+ /// <param name="loggerFactory">Optional logger factory for slow query logging.</param>
3955 protected EfCoreKitDbContext (
4056 DbContextOptions < TContext > options ,
4157 EfCoreKitOptions kitOptions ,
4258 IUserProvider ? userProvider ,
43- ITenantProvider ? tenantProvider )
59+ ITenantProvider ? tenantProvider ,
60+ ILoggerFactory ? loggerFactory = null )
4461 : base ( options )
4562 {
4663 _options = kitOptions ?? throw new ArgumentNullException ( nameof ( kitOptions ) ) ;
4764 _userProvider = userProvider ;
4865 _tenantProvider = tenantProvider ;
66+ _loggerFactory = loggerFactory ;
4967 }
5068
5169 /// <summary>
@@ -54,10 +72,24 @@ protected EfCoreKitDbContext(
5472 protected EfCoreKitOptions Options => _options ;
5573
5674 /// <inheritdoc />
57- public override async Task < int > SaveChangesAsync ( CancellationToken cancellationToken = default )
75+ protected override void OnConfiguring ( DbContextOptionsBuilder optionsBuilder )
5876 {
59- OnBeforeSaveChanges ( ) ;
60- return await base . SaveChangesAsync ( cancellationToken ) ;
77+ base . OnConfiguring ( optionsBuilder ) ;
78+
79+ if ( _options . AuditTrailEnabled )
80+ optionsBuilder . AddInterceptors ( new AuditInterceptor ( _options , _userProvider ) ) ;
81+
82+ if ( _options . SoftDeleteEnabled )
83+ optionsBuilder . AddInterceptors ( new SoftDeleteInterceptor ( _options , _userProvider ) ) ;
84+
85+ if ( _options . MultiTenancyEnabled )
86+ optionsBuilder . AddInterceptors ( new TenantInterceptor ( _options , _tenantProvider ) ) ;
87+
88+ if ( _options . SlowQueryThreshold is not null )
89+ {
90+ var logger = _loggerFactory ? . CreateLogger < SlowQueryInterceptor > ( ) ;
91+ optionsBuilder . AddInterceptors ( new SlowQueryInterceptor ( _options , logger ) ) ;
92+ }
6193 }
6294
6395 /// <inheritdoc />
@@ -67,23 +99,16 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
6799 ConfigureGlobalFilters ( modelBuilder ) ;
68100 }
69101
70- /// <summary>
71- /// Hook called before changes are saved. Handles audit trail, soft delete, and tenant assignment.
72- /// </summary>
73- private void OnBeforeSaveChanges ( )
74- {
75- // TODO: Implement audit trail (HandleAuditableEntities)
76- // TODO: Implement soft delete interception (HandleSoftDeletableEntities)
77- // TODO: Implement tenant assignment (HandleTenantEntities)
78- }
79-
80102 /// <summary>
81103 /// Applies global query filters for soft delete and multi-tenancy.
82104 /// </summary>
83105 /// <param name="modelBuilder">The model builder.</param>
84106 private void ConfigureGlobalFilters ( ModelBuilder modelBuilder )
85107 {
86- // TODO: Apply ISoftDeletable global filter
87- // TODO: Apply ITenantEntity global filter
108+ if ( _options . SoftDeleteEnabled )
109+ SoftDeleteQueryFilter . Apply ( modelBuilder ) ;
110+
111+ if ( _options . MultiTenancyEnabled )
112+ TenantQueryFilter . Apply ( modelBuilder , _tenantProvider ) ;
88113 }
89114}
0 commit comments