Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Model is rebuilt when the database root changes #34476

Open
koenigst opened this issue Aug 20, 2024 · 1 comment · May be fixed by #34477
Open

Model is rebuilt when the database root changes #34476

koenigst opened this issue Aug 20, 2024 · 1 comment · May be fixed by #34477

Comments

@koenigst
Copy link
Contributor

We use the databaseRoot parameter of UseInMemoryDatabase to provide test isolation when using the in-memory provider. Unfortunately setting this parameter leads to a huge performance overhead because the model is rebuilt for every test.

Reproduction steps

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using Xunit;

public sealed class ModelRebuild
{
    [Fact]
    public void NoDatabaseRootInOptions_ModelReused()
    {
        var options1 = new DbContextOptionsBuilder<TestContext>()
            .UseInMemoryDatabase("test1")
            .Options;
        var options2 = new DbContextOptionsBuilder<TestContext>()
            .UseInMemoryDatabase("test2")
            .Options;

        using var context1 = new TestContext(options1);
        using var context2 = new TestContext(options2);

        Assert.Same(context1.Model, context2.Model);
    }

    [Fact]
    public void DatabaseRootSetInOptions_ModelRebuilt()
    {
        var options1 = new DbContextOptionsBuilder<TestContext>()
            .UseInMemoryDatabase("test1", new InMemoryDatabaseRoot())
            .Options;
        var options2 = new DbContextOptionsBuilder<TestContext>()
            .UseInMemoryDatabase("test2", new InMemoryDatabaseRoot())
            .Options;

        using var context1 = new TestContext(options1);
        using var context2 = new TestContext(options2);

        Assert.NotSame(context1.Model, context2.Model);
    }

    private sealed class TestContext(DbContextOptions<TestContext> options) : DbContext(options);
}

EF Core version

Database provider: Microsoft.EntityFrameworkCore.InMemory 8.0.8
Target framework: .NET 8.0
Operating system: Windows 11 22H2
IDE: Visual Studio 2022 (64-bit) 17.10.1

@koenigst
Copy link
Contributor Author

As the fix is quite simple (do not cache the database root as a singleton) I will already submit a PR.

koenigst added a commit to koenigst/efcore that referenced this issue Aug 20, 2024
…he singleton options.

- Remove the DatabaseRoot from the InMemoryOptionsExtension service provider equality condition.
- Remove the DatabaseRoot from the InMemorySingletonOptions.
- Resolve the IInMemoryStore in a scoped service (IInMemoryStoreProvider) instead of a singleton service (IInMemoryStoreCache).
- Fall back to the DatabaseRoot stored in a singleton service (IInMemoryDatabaseRootCache) if the options does not specify one.

Fixes dotnet#34476
@ajcvickers ajcvickers self-assigned this Aug 26, 2024
@ajcvickers ajcvickers added this to the Backlog milestone Aug 26, 2024
@ajcvickers ajcvickers removed their assignment Aug 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants