最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - Cannot remove DBContext from DI - Stack Overflow

programmeradmin0浏览0评论

I am writing XUnit integration tests for my ASP.NET Core Web API. I reconfigure my app in CustomWebApplicationFactory to replace original DbContext with the EFCore InMemoryDataBase like this:

protected override void ConfigureWebHost(IWebHostBuilder builder)
{
    builder.ConfigureServices(services =>
    {
        var context = services.FirstOrDefault(descriptor => descriptor.ServiceType == typeof(DartsDbContext));

        if (context != null)
        {
            services.Remove(context);
            var options = services.Where(r => (r.ServiceType == typeof(DbContextOptions))
              || (r.ServiceType.IsGenericType && r.ServiceType.GetGenericTypeDefinition() == typeof(DbContextOptions<>))).ToArray();

            foreach (var option in options)
            {
                services.Remove(option);
            }
        }

        services.AddDbContext<DartsDbContext>(options =>
        {
            options.UseInMemoryDatabase("InMemoryDbForTesting");
        });
    });
}

I get this error:

One or more errors occurred. (Services for database providers 'Npgsql.EntityFrameworkCore.PostgreSQL', 'Microsoft.EntityFrameworkCore.InMemory' have been registered in the service provider. Only a single database provider can be registered in a service provider

If I delete the line of code in Program.cs file that adds the original DbContext, it works because only one DbContext exists.

I want to save my original DbContext injection in Program.cs and I want CustomWebApplicationFactory to replace it just for tests.

I am writing XUnit integration tests for my ASP.NET Core Web API. I reconfigure my app in CustomWebApplicationFactory to replace original DbContext with the EFCore InMemoryDataBase like this:

protected override void ConfigureWebHost(IWebHostBuilder builder)
{
    builder.ConfigureServices(services =>
    {
        var context = services.FirstOrDefault(descriptor => descriptor.ServiceType == typeof(DartsDbContext));

        if (context != null)
        {
            services.Remove(context);
            var options = services.Where(r => (r.ServiceType == typeof(DbContextOptions))
              || (r.ServiceType.IsGenericType && r.ServiceType.GetGenericTypeDefinition() == typeof(DbContextOptions<>))).ToArray();

            foreach (var option in options)
            {
                services.Remove(option);
            }
        }

        services.AddDbContext<DartsDbContext>(options =>
        {
            options.UseInMemoryDatabase("InMemoryDbForTesting");
        });
    });
}

I get this error:

One or more errors occurred. (Services for database providers 'Npgsql.EntityFrameworkCore.PostgreSQL', 'Microsoft.EntityFrameworkCore.InMemory' have been registered in the service provider. Only a single database provider can be registered in a service provider

If I delete the line of code in Program.cs file that adds the original DbContext, it works because only one DbContext exists.

I want to save my original DbContext injection in Program.cs and I want CustomWebApplicationFactory to replace it just for tests.

Share Improve this question edited Feb 3 at 13:45 marc_s 755k184 gold badges1.4k silver badges1.5k bronze badges asked Feb 3 at 12:15 ShkerbsShkerbs 232 bronze badges 6
  • Why does the code differ from the documentation code ? Why FirstOrDefault instead of SingleOrDefault? If the same DbContext is registered multiple times the application code has a bug and should be fixed, not covered up. Your code removes only the first of the possible duplicates – Panagiotis Kanavos Commented Feb 3 at 13:28
  • Please post the parts of your Program.cs that configure the host and DI, your DartsDbContext and your CustomWebApplicationFactory. Somehow these classes end up registering multiple database providers, Also post the full exception text, ie including the stack trace and any inner exceptions. – Panagiotis Kanavos Commented Feb 3 at 13:31
  • @PanagiotisKanavos it seems that the doc is outdated for .NET 9 – Guru Stron Commented Feb 3 at 16:02
  • Just to be sure - are you using .NET 9? – Guru Stron Commented Feb 3 at 16:03
  • 1 The solution helped. @GuruStron i am using 8 and efcore 9. – Shkerbs Commented Feb 4 at 6:13
 |  Show 1 more comment

1 Answer 1

Reset to default 1

It seems that since .NET 9 (EF Core 9) IDbContextOptionsConfiguration<TContext> (introduced in .NET 9) should be removed also:

var optionsConfig = services.Where(r => r.ServiceType.IsGenericType && r.ServiceType.GetGenericTypeDefinition() == typeof(IDbContextOptionsConfiguration<>))
    .ToArray();

foreach (var option in optionsConfig)
{
    services.Remove(option);
}

Current version of the docs for Customize WebApplicationFactory seems to be invalid and there is an issue about it raised @github.

See also:

  • Add API to remove provider configuration at github
发布评论

评论列表(0)

  1. 暂无评论