Not available to use dbContext in .UseDbContext<MyDbContext> in Audit.Core.Configuration.Setup
Im not available to use UseDbContext<MyDbContext> in my UseEntityFramework configuration, im getting this error 'Constructor on type 'DbContext' not found.', i added that line because i had the loop problem, it work but getting the service of my applicationDbContext like this 'return services.BuildServiceProvider().GetService<ApplicationDbContext>()', but i think thats not the right way, i already added the [AuditIgnore] to my Auidtable entity, ill leave my snippets of code below
this is my startup config
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public virtual void ConfigureServices(IServiceCollection services)
{
// Configure services
services.AddDbContext<ApplicationDbContext>(c => c
.UseSqlServer(Configuration.GetConnectionString("EntityFrameworkConnection"))
.AddInterceptors(new AuditSaveChangesInterceptor()));
Audit.Core.Configuration.Setup()
.UseEntityFramework(_ => _
.UseDbContext<ApplicationDbContext>()
.AuditTypeMapper(t => typeof(Auditable))
.AuditEntityAction<Auditable>((ev, entry, entity) =>
{
entity.Comments = "";
entity.Action = entry.Action;
entity.Ip = "";
entity.UserName = ev.Environment.UserName;
entity.ActionDate = DateTimeOffset.UtcNow;
entity.Longitude = 0;
entity.Latitude = 0;
entity.Browser = "";
entity.Success = ev.GetEntityFrameworkEvent().Success;
})
.IgnoreMatchedProperties(true));
}
}
im getting this error Constructor on type 'DbContext' not found.
this is my db context
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<Auditable> Auditable { get; set; }
public DbSet<CurrencyPair> CurrencyPair { get; set; }
}
if i do tihis:
.UseDbContext(ev =>
{
return services.BuildServiceProvider().GetService<ApplicationDbContext>();
})
instead of:
.UseDbContext<ApplicationDbContext>()
works but i dont thinks is the right way
Yes, that's one way to do it.
It may seem incorrect because you are using the service provider in the method that should be configuring the service provider...
I think it would be better to move the Audit.Core.Configuration.Setup() call to the Startup.Configure method.
For example:
public void Configure(IApplicationBuilder app)
{
Audit.Core.Configuration.Setup()
.UseEntityFramework(x => x
.UseDbContext(ev => app.ApplicationServices.GetService<ApplicationDbContext>()));
}
Check this SO answer: https://stackoverflow.com/a/32461714/122195
i tried that moving the Audit.Core.Configuration.Setup() to the Startup.Configure method, but now im getting this error
Cannot resolve scoped service 'Demo.Data.ApplicationDbContext' from root provider., using this
.UseDbContext(ev => app.ApplicationServices.GetService<ApplicationDbContext>())
Please check this: https://github.com/thepirat000/Audit.NET/issues/539
Maybe this should work for you:
Audit.Core.Configuration.Setup()
.UseEntityFramework(ef => ef
.UseDbContext(ev => app.ApplicationServices.CreateScope().ServiceProvider.GetRequiredService<ApplicationDbContext>())
.DisposeDbContext()
....);
Thanks, it worked, by created a new scope im getting a new instance of DbContext that works well, but im having a little trouble, when i try to get a registered scope service im getting a new instance of that service, and i would like to get the current scope service in a request
Startup()
services.AddScoped<IRequestContext, RequestContext>();
Configure(IApplicationBuilder app)
var serviceProvider = app.ApplicationServices.CreateScope().ServiceProvider;
Audit.Core.Configuration.Setup()
.UseEntityFramework(_ => _
.UseDbContext(ev =>
{
return serviceProvider.GetRequiredService<ApplicationDbContext>();
})
.AuditTypeMapper(t => typeof(Auditable))
.AuditEntityAction<Auditable>((ev, entry, entity) =>
{
**var requestContext = serviceProvider.GetRequiredService<IRequestContext>();** //<-- This line
})
.IgnoreMatchedProperties(true));
i would like to know if there is a way to use DI to get that current scoped service in a request, or if i can apply something in a AddCustomAction method, im trying to fill some fields with user data that i got in that requestContext.
Yes, you can !
Since you can access the DbContext from the event, and the DbContext provides access to service provider:
.AuditEntityAction<Auditable>((ev, entry, entity) =>
{
var requestContext = ev.GetEntityFrameworkEvent().GetDbContext().GetService<IRequestContext>();
})
Works perfect!, thank you for the detailed explanation and your answers @thepirat000