Closed rezathecoder closed 4 weeks ago
Hello @rezathecoder if you are using the BulkSaveChanges()
which supports Change Tracking then Yes it's possible albeit with a twist. your Interceptor has to inherit from DbCommandInterceptor
. Inheriting from SaveChangesInterceptor
would not cut it when using BulkSaveChanges()
.
Hello @rezathecoder if you are using the
BulkSaveChanges()
which supports Change Tracking then Yes it's possible albeit with a twist. your Interceptor has to inherit fromDbCommandInterceptor
. Inheriting fromSaveChangesInterceptor
would not cut it when usingBulkSaveChanges()
.
Can you please guide me so i can imlplement that? I need to do some work before and after saving on entries
Hello @rezathecoder if you are using the
BulkSaveChanges()
which supports Change Tracking then Yes it's possible albeit with a twist. your Interceptor has to inherit fromDbCommandInterceptor
. Inheriting fromSaveChangesInterceptor
would not cut it when usingBulkSaveChanges()
.Can you please guide me so i can imlplement that? I need to do some work before and after saving on entries
below is an example of doing work before saving the entries. for after saving the entries, you have to override the NonQueryExecuted
and NonQueryExecutedAsync
methods.
public sealed class NonQueryAuditableEntityInterceptor : DbCommandInterceptor
{
private readonly ILogger<NonQueryAuditableEntityInterceptor> _logger;
private readonly TimeProvider _timeProvider;
public NonQueryAuditableEntityInterceptor(ILogger<NonQueryAuditableEntityInterceptor> logger, TimeProvider timeProvider)
{
_logger = logger;
_timeProvider = timeProvider;
}
public override InterceptionResult<int> NonQueryExecuting(DbCommand command, CommandEventData eventData, InterceptionResult<int> result)
{
if (eventData.Context is not null)
{
UpdateAuditableEntities(eventData.Context);
}
return base.NonQueryExecuting(command, eventData, result);
}
public override ValueTask<InterceptionResult<int>> NonQueryExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult<int> result, CancellationToken cancellationToken = default)
{
if (eventData.Context is not null)
{
UpdateAuditableEntities(eventData.Context);
}
return base.NonQueryExecutingAsync(command, eventData, result, cancellationToken);
}
private void UpdateAuditableEntities(DbContext context)
{
var utcNow = _timeProvider.GetUtcNow().UtcDateTime;
var changeTracker = context.ChangeTracker;
changeTracker.DetectChanges();
var entityEntries = changeTracker.Entries<IAuditableEntity>().Where(x => x.State == EntityState.Added || x.State == EntityState.Modified).ToList();
foreach (var entityEntry in entityEntries)
{
switch (entityEntry.State)
{
case EntityState.Added:
SetCurrentPropertyValue(entityEntry, nameof(IAuditableEntity.CreatedOnUtc), utcNow);
break;
case EntityState.Modified:
SetCurrentPropertyValue(entityEntry, nameof(IAuditableEntity.ModifiedOnUtc), utcNow);
break;
}
}
return;
static void SetCurrentPropertyValue(EntityEntry entry, string propertyName, DateTime utcNow) => entry.Property(propertyName).CurrentValue = utcNow;
}
}
public interface IAuditableEntity
{
DateTime CreatedOnUtc { get; }
DateTime? ModifiedOnUtc { get; }
}
*** Remember to add the Interceptor in your DbContextOptionsBuilder
instance
Hi @Xor-el Is it possible add additional data to save to another entity?
@ArtemMaslow I have no idea.
@rezathecoder one way to add some custom logic would be to override BulkMethods you use as explained here:
Create extension method #56-comment
Another option would be to use config CustomSqlPostProcess (check info in ReadMe)
Regarding Interceptors here is some useful info: https://learn.microsoft.com/en-us/ef/core/logging-events-diagnostics/interceptors https://medium.com/the-tech-collective/part-3-using-interceptors-with-entity-framework-core-0475f49c8947
Hi Is it possible to support EF interceptors when using BulkSaveChanges ? @borisdj