Wojciech Szabowicz
Wojciech Szabowicz

Reputation: 4198

Entity Framework Core and UseInMemoryDatabase

I am trying to write a tests using Entity Framework Core UseInMemoryDatabase so my setup looks like:

    [SetUp]
    public void Setup()
    {
        this.ContextOptions = new DbContextOptionsBuilder<GeneralContext>()
            .UseInMemoryDatabase(databaseName: "DiagAc2Tests")
            .Options;
    }

I dont know if it is needed, but context looks like:

public class GeneralContext : DbContext
{
    public DbSet<Entities.Application> Applications { get; set; }
    public GeneralContext() { }
    public GeneralContext(DbContextOptions<GeneralContext> options) : base(options) { }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        var config = new DatabaseConfiguration();
        optionsBuilder.UseNpgsql(config.GetConnectionString());
    }
}

I use this context through out my application and it works, so my test looks like:

        public async Task CreateApplicationByService()
        {
            Mock<DTO.IApplication> mock = new Mock<DTO.IApplication>();
            mock.SetupProperty(f => f.Name, "Application");
            mock.SetupProperty(f => f.ProjectId, 666);
            mock.SetupProperty(f => f.ConfigFilePath, null);

            DTO.IApplication appDto = mock.Object;

            var entity = this.Mapper.Map<DTO.IApplication, Application>(appDto);
            try
            {
                using var context = new GeneralContext(this.ContextOptions);
                await context .ApplicationRepository.Add(entity);
            }
            catch (Exception ex)
            {
                var t = ex;
            }

            var one = 1;
            var two = 2;
            Assert.True(one != two);
        }

I dont have any asserts, thats why that silly assert is added, yet but when I add record through context I am getting:

Services for database providers 'Microsoft.EntityFrameworkCore.InMemory', 'Npgsql.EntityFrameworkCore.PostgreSQL' 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.

I done everything according to documentation on MSDN, so waht could be wrong?

Upvotes: 3

Views: 7396

Answers (3)

Jyri
Jyri

Reputation: 56

Did just run into this same issue, and used this method in OnConfiguring

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    if (!optionsBuilder.IsConfigured)
    {
        optionsBuilder.UseSqlServer("connectionstring");
    }
}

Upvotes: 3

Jonathan Busuttil
Jonathan Busuttil

Reputation: 493

In the test project you can use a separate Startup class than your app and you can remove the UseNpgsql from your Startup class in the test project since you want to use In Memory database.

Upvotes: 0

A_kat
A_kat

Reputation: 1537

optionsBuilder.UseNpgsql(config.GetConnectionString());

The mistake is in this line and this an example of inversion of control. You should not call UseNpqSql within OnConfiguring. What this does is that it tried to use 2 databases.

this.ContextOptions = new DbContextOptionsBuilder<GeneralContext>()
        .UseInMemoryDatabase(databaseName: "DiagAc2Tests")
        .Options;

optionsBuilder.UseNpgsql(config.GetConnectionString());

Both of the above statements will be run.

Now the solution to this is to move UseNpgsql outside of configuring and in your app startup class. That of course depends on your project and how you want to achieve it.

Upvotes: 7

Related Questions