External Data Resolution #734
-
|
I am using EF Core in a .NET 8 project to manage database operations. For auditing purposes, I am leveraging the Audit.EntityFramework.Core library (27.2.0) to log changes made to entities. One of requirements is to log human-readable values instead of ids for certain properties. The ids correspond to data residing in an external source. For example, I have an Order entity which contains a DeliveryMethodId property: public sealed class Order
{
public decimal OrderId { get; set; }
public decimal DeliveryMethodId { get; set; }
// Other properties...
}The details for delivery methods are stored in an external system. One can fetch them using a repository: public sealed record DeliveryMethod
{
public required decimal DeliveryMethodId { get; init; }
public string? Name { get; init; }
}public interface IDeliveryMethodRepository
{
Task<DeliveryMethod?> GetDeliveryMethodByIdOrDefaultAsync(decimal deliveryMethodId, CancellationToken cancellationToken = default);
Task<IReadOnlyCollection<DeliveryMethod>> GetDeliveryMethodsAsync(CancellationToken cancellationToken = default);
}I need to replace the DeliveryMethodId with the corresponding DeliveryMethod's Name. Here is the current configuration of the application's db context: public sealed class ApplicationDbContext : AuditDbContext
{
public DbSet<Order> Orders => Set<Order>();
// Other db sets...
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
AuditDataProvider = new EntityFrameworkDataProvider(entityFrameworkProviderConfigurator =>
{
entityFrameworkProviderConfigurator
.UseDbContext<ApplicationDbContext>(options)
.AuditTypeMapper(_ => typeof(EntityLog))
.AuditEntityAction<EntityLog>((auditEvent, eventEntry, entityLog) =>
{
entityLog.Table = eventEntry.Table;
entityLog.EntityId = string.Join(",", eventEntry.PrimaryKey.Values);
entityLog.EntityType = eventEntry.EntityType;
entityLog.Action = Enum.Parse<DatabaseAction>(eventEntry.Action);
foreach (var property in eventEntry.Changes ?? [])
{
var rowChange = new RowChange
{
ColumnName = property.ColumnName,
OldValue = property.OriginalValue,
NewValue = property.NewValue
};
entityLog.Changes.Add(rowChange);
}
entityLog.UserId = Thread.CurrentPrincipal?.GetUserId() ?? 0;
entityLog.Timestamp = new DateTimeOffset(auditEvent.StartDate);
})
.IgnoreMatchedProperties();
});
}I could inject an IDeliveryMethodRepository in the ApplicationDbContext's constructor, fetch the required data in the AuditEntityAction, and set the RowChange's OldValue and NewValue to delivery method names... but I am not sure it is the right approach. Any insights or suggestions would be greatly appreciated! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
|
As long as the repository doesn't depend on your DbContext, it should be fine. I would probably extract the Audit Entity action into a dedicated method within the DbContext: public sealed class ApplicationDbContext : AuditDbContext
{
private readonly IDeliveryMethodRepository _deliveryMethodRepository;
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, IDeliveryMethodRepository deliveryMethodRepository) : base(options)
{
_deliveryMethodRepository = deliveryMethodRepository;
AuditDataProvider = new EntityFrameworkDataProvider(entityFrameworkProviderConfigurator =>
{
entityFrameworkProviderConfigurator
.UseDbContext<ApplicationDbContext>(options)
.AuditTypeMapper(_ => typeof(EntityLog))
.AuditEntityAction<EntityLog>(AuditEntityAction)
.IgnoreMatchedProperties();
});
}
private void AuditEntityAction(AuditEvent auditEvent, EventEntry eventEntry, EntityLog entityLog)
{
entityLog.Table = eventEntry.Table;
// use _deliveryMethodRepository ...
}
} |
Beta Was this translation helpful? Give feedback.
As long as the repository doesn't depend on your DbContext, it should be fine. I would probably extract the Audit Entity action into a dedicated method within the DbContext: