I want to use https://github.com/koenbeuk/EntityFrameworkCore.Triggered in my ABP solution but I can't figure out how to register the triggers with my AbpDbContext.
This is what the documentation for EntityFrameworkCore.Triggered suggests:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services
.AddDbContext<ApplicationContext>(options => {
options.UseTriggers(triggerOptions => {
triggerOptions.AddTrigger<MyTrigger>();
});
})
}
}
How can I use this library with with ABP?
10 Answer(s)
-
0
Hi,
Open
*.EntityFrameworkCoreModule
and findConfigure<AbpDbContextOptions>
:Configure<AbpDbContextOptions>(options => { /* The main point to change your DBMS. * See also MyProjectNameMigrationsDbContextFactory for EF Core tooling. */ options.UseSqlServer(); options.Configure(c => { c.DbContextOptions.UseTriggers(); }); });
-
0
Thanks! However, when I try that I get an error on application start:
An unhandled exception occurred while processing the request.
InvalidOperationException: No database provider has been configured for this DbContext. A provider can be configured by overriding the 'DbContext.OnConfiguring' method or by using 'AddDbContext' on the application service provider. If 'AddDbContext' is used, then also ensure that your DbContext type accepts a DbContextOptions<TContext> object in its constructor and passes it to the base constructor for DbContext.
Microsoft.EntityFrameworkCore.Internal.DbContextServices.Initialize(IServiceProvider scopedProvider, IDbContextOptions contextOptions, DbContext context)
Stack trace:
<br>
InvalidOperationException: No database provider has been configured for this DbContext. A provider can be configured by overriding the 'DbContext.OnConfiguring' method or by using 'AddDbContext' on the application service provider. If 'AddDbContext' is used, then also ensure that your DbContext type accepts a DbContextOptions<TContext> object in its constructor and passes it to the base constructor for DbContext. Microsoft.EntityFrameworkCore.Internal.DbContextServices.Initialize(IServiceProvider scopedProvider, IDbContextOptions contextOptions, DbContext context) Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider() Microsoft.EntityFrameworkCore.DbContext.get_ChangeTracker() Volo.Abp.EntityFrameworkCore.AbpDbContext<TDbContext>.Initialize(AbpEfCoreDbContextInitializationContext initializationContext) Volo.Abp.Uow.EntityFrameworkCore.UnitOfWorkDbContextProvider<TDbContext>.CreateDbContextAsync(IUnitOfWork unitOfWork, string connectionStringName, string connectionString) Volo.Abp.Uow.EntityFrameworkCore.UnitOfWorkDbContextProvider<TDbContext>.GetDbContextAsync() Volo.Abp.Domain.Repositories.EntityFrameworkCore.EfCoreRepository<TDbContext, TEntity>.GetDbSetAsync() Volo.Abp.LanguageManagement.EntityFrameworkCore.EfCoreLanguageRepository.GetListAsync(bool isEnabled) Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous<TResult>(IInvocation invocation, IInvocationProceedInfo proceedInfo) Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue<TResult>.ProceedAsync() Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation) Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter<TInterceptor>.InterceptAsync<TResult>(IInvocation invocation, IInvocationProceedInfo proceedInfo, Func<IInvocation, IInvocationProceedInfo, Task<TResult>> proceed) Volo.Abp.LanguageManagement.DatabaseLanguageProvider.oBPl0rvdv() Volo.Abp.Caching.DistributedCache<TCacheItem, TCacheKey>.GetOrAddAsync(TCacheKey key, Func<Task<TCacheItem>> factory, Func<DistributedCacheEntryOptions> optionsFactory, Nullable<bool> hideErrors, bool considerUow, CancellationToken token) Volo.Abp.LanguageManagement.DatabaseLanguageProvider.GetLanguagesAsync() Microsoft.AspNetCore.RequestLocalization.DefaultAbpRequestLocalizationOptionsProvider.GetLocalizationOptionsAsync() Microsoft.AspNetCore.RequestLocalization.AbpRequestLocalizationMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) Microsoft.AspNetCore.Builder.UseMiddlewareExtensions+<>c__DisplayClass6_1+<<UseMiddlewareInterface>b__1>d.MoveNext() Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
-
0
Try:
Configure<AbpDbContextOptions>(options => { options.Configure(c => { c.UseSqlServer(); c.DbContextOptions.UseTriggers(); }); });
-
0
Thanks, that change made the trigger be registered and triggered.
However the dependency injection failed while instantiating my trigger class. I am injecting an IRepository into it and got an exception:
System.InvalidOperationException: 'Unable to resolve service for type 'MyProjectName.IMyEntityRepository' while attempting to activate 'MyProjectName.BeforeSaveTrigger'.'
I solved this by including the line
t.UseApplicationScopedServiceProviderAccessor(_ => context.Services.GetServiceProviderOrNull());
as below since the the documentation at https://github.com/koenbeuk/EntityFrameworkCore.Triggered/wiki/Dependency-injection mentions this solution:Configure a method that returns the current relevant ServiceProvider. This can be done by providing a method through: triggerOptions.UseApplicationScopedServiceProviderAccessor(sp => ...). The first argument will be either the application ServiceProvider if available or otherwise the internal service provider.
Does this seem like a reasonable solution or will it break something?
options.Configure(c => { c.UseSqlServer(); c.DbContextOptions.UseTriggers(t => { t.UseApplicationScopedServiceProviderAccessor(_ => context.Services.GetServiceProviderOrNull()); t.AddTrigger<BeforeSaveTrigger>(); }); });
-
0
hi,
This way will be better
c.DbContextOptions.UseTriggers(t => { t.UseApplicationScopedServiceProviderAccessor(_ => _.GetRequiredService<IHttpContextAccessor>().HttpContext?.RequestServices); });
-
0
c.DbContextOptions.UseTriggers(t => { t.UseApplicationScopedServiceProviderAccessor(_ => _.GetRequiredService<IHttpContextAccessor>().HttpContext?.RequestServices); });
Doing this way I get
System.InvalidOperationException: 'No service for type 'Microsoft.AspNetCore.Http.IHttpContextAccessor' has been registered.'
on application start. -
0
After my test, the following code is ok.
Configure<AbpDbContextOptions>(options => { options.Configure(c => { c.UseSqlServer(); c.DbContextOptions.UseTriggers(t => { t.UseApplicationScopedServiceProviderAccessor(_ => _.CreateScope().ServiceProvider); }); }); });
-
0
After my test, the following code is ok.
Sorry, but I get
System.InvalidOperationException: 'Unable to resolve service for type 'MyProjectName.IMyEntityRepository' while attempting to activate 'MyProjectName.BeforeSaveTrigger'.'
doing it this way as well. -
0
Can you share the full logs?
-
0
This question has been automatically marked as stale because it has not had recent activity.