Webion.Extensions.EntityFrameworkCore.ChangeTracking
1.0.2
dotnet add package Webion.Extensions.EntityFrameworkCore.ChangeTracking --version 1.0.2
NuGet\Install-Package Webion.Extensions.EntityFrameworkCore.ChangeTracking -Version 1.0.2
<PackageReference Include="Webion.Extensions.EntityFrameworkCore.ChangeTracking" Version="1.0.2" />
paket add Webion.Extensions.EntityFrameworkCore.ChangeTracking --version 1.0.2
#r "nuget: Webion.Extensions.EntityFrameworkCore.ChangeTracking, 1.0.2"
// Install Webion.Extensions.EntityFrameworkCore.ChangeTracking as a Cake Addin #addin nuget:?package=Webion.Extensions.EntityFrameworkCore.ChangeTracking&version=1.0.2 // Install Webion.Extensions.EntityFrameworkCore.ChangeTracking as a Cake Tool #tool nuget:?package=Webion.Extensions.EntityFrameworkCore.ChangeTracking&version=1.0.2
Change tracking extensions for Entity Framework Core db contexts.
Usage
Implement the IChangeTrackingInfoDbo interface on the table that will hold the tracking information.
public sealed class ChangeTrackingInfoDbo : IChangeTrackingInfoDbo, IEntityTypeConfiguration<ChangeTrackingInfoDbo>
{
public Guid Id { get; set; }
public string? TargetId { get; set; }
public string? EntityName { get; set; }
public string? CreatedByName { get; set; }
public decimal Version { get; set; }
public DateTimeOffset Timestamp { get; set; }
// Note that you can add addional fields and relations.
public Guid? CreatedByUserId { get; set; }
public JsonDocument? Metadata { get; set; }
public ChangeTrackingOperation Operation { get; set; }
public UserDbo? User { get; set; }
public void Configure(EntityTypeBuilder<ChangeTrackingInfoDbo> builder)
{
builder.ToTable("change_tracking_info", Schemas.Common);
builder.HasKey(x => x.Id);
builder.Property(x => x.Version).IsRequired().HasDefaultValue(0m);
builder.Property(x => x.Timestamp).IsRequired().HasDefaultValueSql("now()");
builder.Property(x => x.CreatedByUserId).IsRequired(false);
builder.Property(x => x.CreatedByName).IsRequired(false).HasMaxLength(128);
builder.Property(x => x.Metadata).IsRequired(false);
builder.Property(x => x.Operation).IsRequired();
builder.Property(x => x.EntityName).IsRequired();
builder.Property(x => x.TargetId).IsRequired();
// Addional relation with an ipotetic user table
builder
.HasOne(x => x.User)
.WithMany()
.HasPrincipalKey(x => x.Id)
.HasForeignKey(x => x.CreatedByUserId)
.IsRequired(false)
.OnDelete(DeleteBehavior.SetNull);
}
}
Implement the db context interface.
public sealed class MyDbContext : DbContext, IChangeTrackingDbContext<ChangeTrackingInfoDbo>
{
private readonly IEnumerable<IInterceptor> _interceptors;
// This property is needed only for this example, as we will be tracking
// the user that makes the queries
public ClaimsPrincipal? Principal { get; set; }
public MyDbContext(DbContextOptions<MyDbContext> options, IEnumerable<IInterceptor> interceptors) : base(options)
{
_interceptors = interceptors;
}
public DbSet<ChangeTrackingInfoDbo> TrackingInfo { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ApplyConfigurationsFromAssembly(typeof(MyDbContext).Assembly);
}
protected override void OnConfiguring(DbContextOptionsBuilder builder)
{
base.OnConfiguring(builder);
// This line is required
// The library relies on ef core interceptors.
builder.AddInterceptors(_interceptors);
}
}
Create any custom interceptor to enrich the data.
For example, in this case we will track our custom User
property for each Api request.
// Custom aspnet core middleware that enriches the db context with
// the current user that is making the api request.
public sealed class ChangeTrackingMiddleware
{
private readonly RequestDelegate _next;
public ChangeTrackingMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext httpContext, MyDbContext dbContext)
{
dbContext.Principal = httpContext.User;
await _next(httpContext);
}
}
// Custom interceptor that enriches the new row with information retrieved
// from the db context.
public sealed class ChangeTrackingInfoDboDecorator : IChangeTrackingInfoDecorator<ChangeTrackingInfoDbo>
{
public void Decorate(ChangeTrackingContext context, ChangeTrackingInfoDbo dbo)
{
if (context.DbContext is not MyDbContext db)
return;
var rawUserId = db.Principal?.FindFirstValue(ClaimTypes.NameIdentifier);
var userEmail = db.Principal?.FindFirstValue(ClaimTypes.Email);
if (Guid.TryParse(rawUserId, out var userId))
dbo.CreatedByUserId = userId;
dbo.CreatedByName = userEmail;
}
}
Register the services.
builder.Services.AddTransient<IChangeTrackingInfoDecorator<ChangeTrackingInfoDbo>, ChangeTrackingInfoDboDecorator>();
builder.Services.AddChangeTracking<MyDbContext, ChangeTrackingInfoDbo>();
Once the services are registered, each Delete, Insert and Update operation will be tracked automatically, with new rows being created in the configured table.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. |
-
net9.0
- Microsoft.EntityFrameworkCore (>= 9.0.0)
- Microsoft.EntityFrameworkCore.Abstractions (>= 9.0.0)
- Microsoft.EntityFrameworkCore.Relational (>= 9.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 9.0.0)
- System.Reactive (>= 6.0.1)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Webion.Extensions.EntityFrameworkCore.ChangeTracking:
Package | Downloads |
---|---|
Webion.Marketplace.Licensing
Webion marketplace licensing utilities and managers |
GitHub repositories
This package is not used by any popular GitHub repositories.