Search code examples
c#ef-core-3.0

How to use a Service or DbContext inside DbCommandInterceptor?


I have an application that syncs data from a MySql database to a SQL Server database.

Considering those two DbContext services:

services.AddDbContext<SqlServerContext>(options => options
    .UseSqlServer(Configuration.GetConnectionString("SqlServer")));

services.AddDbContext<MySqlContext>(options => options
    .UseMySql(Configuration.GetConnectionString("MySql"))
    .AddInterceptors(new MySqlInterceptor()));

In the MySqlInterceptor(); I want to inject/resolve/use a Service or even the SqlServerContext, in order to get configurations to modify the CommandText.

Any ideas?


Solution

  • As @vasil mentioned in his answer:

    Depending on the method you are going to override, you will receive CommandEventData object in the method definition which has the DbContext as property.

    In my case though, I wanted to resolve a service that used another DbContext, which proved to be cumbersome; so instead I ended up putting the settings I needed into appsettings.json, and used IConfiguration service to get the setting value and sent it to the Interceptor constructor:

    services.AddDbContext<MySqlContext>(options => options
        .UseMySql(Configuration.GetConnectionString("MySql"))
        .AddInterceptors(new MySqlInterceptor(Configuration["SettingValue"])));
    

    Note: If you landed on this answer and was looking for a way to resolve a service inside the ConfigureService method, without calling BuildServiceProvider which, like David Fowler says on a Github issue, you'd be:

    building the container while trying to build it

    and you'll end up having:

    2 containers and one of them will never be disposed.

    You can do what Nkosi suggests in his answer:

    services.AddScoped<IService>(x => 
        new Service(x.GetRequiredService<IOtherService>(),
                    x.GetRequiredService<IAnotherOne>(), 
                    ""));