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

Improve logging around context model caching #11608

Open
Tracked by #22952
SimonCropp opened this issue Apr 10, 2018 · 6 comments
Open
Tracked by #22952

Improve logging around context model caching #11608

SimonCropp opened this issue Apr 10, 2018 · 6 comments

Comments

@SimonCropp
Copy link
Contributor

SimonCropp commented Apr 10, 2018

So when mapping a view there is a workaround that can be taken.

  • when creating/installing the db dont map the view (to avoid EF creating a table named by the view)
  • when using the db map the view

This can be done by passing a bool into the custom DbContext, so the same context can be used from the installation context and the usage context

public class MyDataContext : DbContext
{
    bool mapViews;
    public DbSet<MyView> MyViews { get; set; }
    public DbSet<MyTable> MyTables { get; set; }

    public MyDataContext(DbContextOptions<MyDataContext> options, bool mapViews) : base(options)
    {
        this.mapViews = mapViews;
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<MyTable>();

        // only map View when not in install mode.
        // otherwise EF incorrectly creates a table named after the view
        // and the view creation scripts will fail with a name conflict
        if (mapViews)
        {
            modelBuilder.Entity<MyView>(entity => { entity.HasKey(e => e.Id); });
        }
        else
        {
            modelBuilder.Ignore<MyView>();
        }
    }
}

However when instantiating two different instances of said context, one with mapViews: false and one with mapViews: true, the entity mapping from the first context seems to be re-used in the second context.

[Fact]
public void ReGenSqlExpress()
{
    using (var context = new MyDataContext(GetOptions(), mapViews: false))
    {
        context.Database.EnsureCreated();
    }

    using (var connection = new SqlConnection(connectionString))
    {
        connection.Open();
        using (var command = connection.CreateCommand())
        {
            command.CommandText = @"
IF (NOT EXISTS (SELECT 1 FROM sys.views WHERE name = 'MyViews'))
BEGIN
EXECUTE('CREATE VIEW MyViews AS SELECT * FROM MyTables');
END";
            command.ExecuteNonQuery();
        }
    }

    using (var context = new MyDataContext(GetOptions(), mapViews: true))
    {
        var myTable = new MyTable
        {
            Title = DateTime.Now.ToString()
        };
        context.MyTables.Add(myTable);
        context.SaveChanges();
        var myViews = context.MyViews.ToList();
        Debug.WriteLine(myViews);
    }
}

This results in a InvalidOperationException : Cannot create a DbSet for 'MyView' because this type is not included in the model for the context.

note that, after the first run to create the db, if you comment out the following

using (var context = new MyDataContext(GetOptions(), mapViews: false))
{
    context.Database.EnsureCreated();
}

The usage of the view will work

full repro: https://github.com/SimonCropp/EfViewMappingRepro

Targeting SQL Server 2016 on windows 2012R2

repro'd with the following nuget combos

  • Microsoft.EntityFrameworkCore 2.0.2 + Microsoft.EntityFrameworkCore.SqlServer 2.0.2
  • Microsoft.EntityFrameworkCore 2.1.0-preview2-final + Microsoft.EntityFrameworkCore.SqlServer 2.1.0-preview2-final

also verified on both netcoreapp2 and net461

@SimonCropp
Copy link
Contributor Author

note that there seems to be some static "type to mapping" caching going on. since if u split the data context into a base and two implementations (https://github.com/SimonCropp/EfViewMappingRepro/tree/inheritanceWorkaround) it seems to work as expected

@ajcvickers
Copy link
Member

@SimonCropp Yes, the model is cached based on a cache key that by default includes the context type, so having a different context type for each model is a good way to handle this. You could instead configure a different cache key--see https://docs.microsoft.com/en-us/ef/core/modeling/dynamic-model for details.

@ajcvickers ajcvickers added the closed-no-further-action The issue is closed and no further action is planned. label Apr 10, 2018
@SimonCropp
Copy link
Contributor Author

@ajcvickers thanks for the prompt reply

@SimonCropp
Copy link
Contributor Author

@ajcvickers given this is very difficult to debug. wouldnt it be better to detect and log that there are conflicting context both loaded into the static context?

@ajcvickers ajcvickers changed the title Entity mapping from one DbContext instance is incorrectly reused in a second DbContext instance Improve logging around context model caching Jul 3, 2018
@ajcvickers
Copy link
Member

Re-purposing this issue to improve the logging for this, as suggested by @SimonCropp.

@ajcvickers ajcvickers reopened this Jul 3, 2018
@ajcvickers ajcvickers added this to the 3.0.0 milestone Jul 3, 2018
@ajcvickers ajcvickers self-assigned this Jul 3, 2018
@SimonCropp
Copy link
Contributor Author

Thanks @ajcvickers

@ajcvickers ajcvickers modified the milestones: 3.0.0, Backlog Aug 3, 2018
@ajcvickers ajcvickers removed propose-punt closed-no-further-action The issue is closed and no further action is planned. labels Aug 3, 2018
@ajcvickers ajcvickers reopened this Feb 26, 2019
@ajcvickers ajcvickers added the good first issue This issue should be relatively straightforward to fix. label Sep 2, 2019
@ajcvickers ajcvickers reopened this Sep 27, 2020
@ajcvickers ajcvickers reopened this Oct 24, 2020
@ajcvickers ajcvickers reopened this May 23, 2022
@ajcvickers ajcvickers removed the good first issue This issue should be relatively straightforward to fix. label May 14, 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
Development

No branches or pull requests

3 participants