SOLVED: EF 8 to 9 migration database provider exception

Services for database providers have been registered in the service provider.

When using XUnit tests in Visual Studio after upgrading my Entity Framework version from 8 to 9 (EF8 to EF9), I started receiving the following error when trying to run my API tests:

System.InvalidOperationException
  HResult=0x80131509
  Message=Services for database providers 'Microsoft.EntityFrameworkCore.SqlServer', 'Microsoft.EntityFrameworkCore.InMemory' have been registered in the service provider. Only a single database provider can be registered in a service provider. If possible, ensure that Entity Framework is managing its service provider by removing the call to 'UseInternalServiceProvider'. Otherwise, consider conditionally registering the database provider, or maintaining one service provider per database provider.
  Source=Microsoft.EntityFrameworkCore
  StackTrace:
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.Initialize(IServiceProvider scopedProvider, DbContextOptions contextOptions, DbContext context)
   at Microsoft.EntityFrameworkCore.DbContext.get_ContextServices()
   at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
   at Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<System.IServiceProvider>.get_Instance()
   at Microsoft.EntityFrameworkCore.Infrastructure.Internal.InfrastructureExtensions.GetService(IInfrastructure`1 accessor, Type serviceType)
   at Microsoft.EntityFrameworkCore.Infrastructure.Internal.InfrastructureExtensions.GetService[TService](IInfrastructure`1 accessor)
   at Microsoft.EntityFrameworkCore.Infrastructure.AccessorExtensions.GetService[TService](IInfrastructure`1 accessor)
   at Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade.get_Dependencies()
   at Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade.EnsureCreated()
   at YTG.RVS.RVAdvert.X.API.Tests.CustomWebApplicationFactory`1.<>c.<ConfigureWebHost>b__0_0(IServiceCollection services) in C:\SourceYTGI\YTG-RVS-RVAdvert-API-PROC\Source\YTG.RVS.RVAdvert.X.API.Tests\CustomWebApplicationFactory.cs:line 78
   at Microsoft.Extensions.Hosting.HostBuilder.InitializeServiceProvider()
   at Microsoft.Extensions.Hosting.HostBuilder.Build()
   at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateHost(IHostBuilder builder)
   at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.ConfigureHostBuilder(IHostBuilder hostBuilder)
   at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.EnsureServer()
   at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.get_Services()
   at YTG.RVS.RVAdvert.X.API.Tests.AdvertTests.get_RVSalesRep() in C:\SourceYTGI\YTG-RVS-RVAdvert-API-PROC\Source\YTG.RVS.RVAdvert.X.API.Tests\AdvertTests.cs:line 63
   at YTG.RVS.RVAdvert.X.API.Tests.AdvertTests.<GETAdvertByUniqueIdTest01>d__8.MoveNext() in C:\SourceYTGI\YTG-RVS-RVAdvert-API-PROC\Source\YTG.RVS.RVAdvert.X.API.Tests\AdvertTests.cs:line 91
   at Xunit.Sdk.TestInvoker`1.<>c__DisplayClass47_0.<<InvokeTestMethodAsync>b__1>d.MoveNext()
   at Xunit.Sdk.ExecutionTimer.<AggregateAsync>d__4.MoveNext()
   at Xunit.Sdk.ExceptionAggregator.<RunAsync>d__9.MoveNext()

This occurs in the CustomWebApplicationFactory class at the line:

db.Database.EnsureCreated();

In your ConfigureWebHost class, there is a line where you remove your stock DBContext and add an in-memory version. That line likely looks like this:

ServiceDescriptor descriptor1 = services.SingleOrDefault(
    d => d.ServiceType == typeof(DbContextOptions<RVSAccountsContext>))!;

It turns out an undocumented breaking change in the EF9 implementation is causing this. DbContextOptions should no longer be used here. If you change this line to the new implementation, it should resolve your issue:

ServiceDescriptor descriptor1 = services.SingleOrDefault(
    d => d.ServiceType == typeof(IDbContextOptionsConfiguration<RVSAccountsContext>))!;

This issue is documented here:

https://github.com/dotnet/efcore/issues/35126#issuecomment-2576387727

Author: Jack Yasgar

Jack Yasgar has been developing software for various industries for two decades. Currently, he utilizes C#, JQuery, JavaScript, SQL Server with stored procedures and/or Entity Framework to produce MVC responsive web sites that converse to a service layer utilizing RESTful API in Web API 2.0 or Microsoft WCF web services. The infrastructure can be internal, shared or reside in Azure. Jack has designed dozens of relational databases that use the proper primary keys and foreign keys to allow for data integrity moving forward. While working in a Scrum/Agile environment, he is a firm believer that quality software comes from quality planning. Without getting caught up in analysis paralysis, it is still possible to achieve a level of design that allows an agile team to move forward quickly while keeping re-work to a minimum. Jack believes, “The key to long term software success is adhering to the SOLID design principles. Software written quickly, using wizards and other methods can impress the business sponsor / product owner for a short period of time. Once the honeymoon is over, the product owner will stay enamored when the team can implement changes quickly and fix bugs in minutes, not hours or days.” Jack has become certified by the Object Management Group as OCUP II (OMG Certified UML Professional) in addition to his certification as a Microsoft Certified Professional. The use of the Unified Modeling Language (UML) provides a visual guide to Use Cases and Activities that can guide the product owner in designing software that meets the end user needs. The software development teams then use the same drawings to create their Unit Tests to make sure that the software meets all those needs. The QA testing team can use the UML drawings as a guide to produce test cases. Once the software is in production, the UML drawings become a reference for business users and support staff to know what decisions are happening behind the scenes to guide their support efforts.

Leave a Reply

Your email address will not be published. Required fields are marked *