Multiple database providers in service provider exception when trying to use InMemoryDatabase for unit testing.
See original GitHub issueI don’t really know if I should ask this here but I can’t find information about this issue anywhere else. I can not seem to get started with xUnit using an EF’s InMemory database. Basically since I don’t want to mess up anything in my SqlServer database I try to create an InMemory database using Microsoft.EntityFrameworkCore.InMemory package like so:
private ZvezdichkaDbContext GetDatabase()
{
var dbOptions = new DbContextOptionsBuilder<MyDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
return new ZvezdichkaDbContext (dbOptions);
}
[Fact]
public void JustTest()
{
//Arrange
var db = GetDatabase();
var p1 = new Product()
{
Description = "Qko",
Name = "First",
Price = 12.12m,
Stock = 15
};
var p2 = new Product()
{
Description = "Qko2",
Name = "Second",
Price = 8.99m,
Stock = 10
};
db.AddRange(p1, p2);
var products = new ProductsDataService(db);
//exception thrown here
//Act
//Assert
}
So far so good. When I try to make a new ProductsDataService with this context it throws the following error:
Exception message:
Message: System.InvalidOperationException : Services for database providers 'Microsoft.EntityFrameworkCore.InMemory', 'Microsoft.EntityFrameworkCore.SqlServer' 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.
Stack trace:
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.Initialize(IServiceProvider scopedProvider, IDbContextOptions contextOptions, DbContext context)
at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
at Microsoft.EntityFrameworkCore.DbContext.SetEntityStates(IEnumerable`1 entities, EntityState entityState)
at Microsoft.EntityFrameworkCore.DbContext.AddRange(IEnumerable`1 entities)
at Microsoft.EntityFrameworkCore.DbContext.AddRange(Object[] entities)
at Zvezdichka.Tests.ProductsDataServiceTests.JustTest() in D:\Github\Zvezdichka-Store\Zvezdichka.Tests\ProductsDataServiceTests.cs:line 40
Steps to reproduce
My ProductsDataService receives the DbContext from the ASP NET Core DI container. The data service implements a GenericDataService<T>. All data services are registered as transient in the services provider.
public abstract class GenericDataService<T> : IGenericDataService<T> where T : class
{
protected DbSet<T> _dbSet;
protected GenericDataService(ZvezdichkaDbContext dbContext)
{
this._dbSet = dbContext.Set<T>();
}
//some common methods for all data services
}
public class ProductsDataService : GenericDataService<Product>, IProductsDataService
{
public ProductsDataService(ZvezdichkaDbContext dbContext) : base(dbContext)
{
}
}
In Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ZvezdichkaDbContext>(options =>
options.UseSqlServer(this.Configuration.GetConnectionString("DefaultConnection")));
//some code
}
I’ve tried anything but can’t find a solution. If someone could please give me a hand that would be massive!
Further technical details
EF Core version: (found in project.csproj or packages.config) Database Provider: (e.g. Microsoft.EntityFrameworkCore.SqlServer) Operating system: IDE: (e.g. Visual Studio 2017 15.4)
Issue Analytics
- State:
- Created 6 years ago
- Comments:7 (3 by maintainers)
To add more, if you want to use multiple providers with same DbContext then passing DbContextOptions through parameter is appropriate way. Since each provider specific context can send in correct options. OnConfiguring is not exclusive to ctor options and hence it will be also run even if options passed into ctor is already configured. If you must have OnConfiguring method to configure one of the providers then you can make it conditional like this
Removed the OnConfiguring method in the DbContext and the problem was solved.