EntityFramework.Docs icon indicating copy to clipboard operation
EntityFramework.Docs copied to clipboard

Configuring an IModelCacheKeyFactory causes "the requested configuration is not stored in the read-optimized model"

Open roji opened this issue 3 years ago • 5 comments

With 6.0.4, configuring an IModelCacheKeyFactory causes the following to be immediately thrown:

Unhandled exception. System.InvalidOperationException: The requested configuration is not stored in the read-optimized model, please use 'DbContext.GetService<IDesignTimeModel>().Model'.
   at Microsoft.EntityFrameworkCore.RelationalModelExtensions.GetCollation(IReadOnlyModel model)
   at Microsoft.EntityFrameworkCore.Metadata.IRelationalModel.get_Collation()
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator.CreateCreateOperations()
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerDatabaseCreator.CreateAsync(CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Storage.RelationalDatabaseCreator.EnsureCreatedAsync(CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Storage.RelationalDatabaseCreator.EnsureCreatedAsync(CancellationToken cancellationToken)
   at Program.<Main>$(String[] args) in /home/roji/projects/test/Program.cs:line 12
   at Program.<Main>$(String[] args) in /home/roji/projects/test/Program.cs:line 12
   at Program.<Main>(String[] args)

This does not happen in 5.0. If this is intentional for some reason, we may be missing a breaking change note?

/cc @AndriySvyryd

Repro
await using var ctx = new BlogContext();
await ctx.Database.EnsureDeletedAsync();
await ctx.Database.EnsureCreatedAsync();

public class BlogContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        => optionsBuilder
            .UseSqlServer(@"Server=localhost;Database=test;User=SA;Password=Abcd5678;Connect Timeout=60;ConnectRetryCount=0;Encrypt=false")
            .ReplaceService<IModelCacheKeyFactory, MyModelCacheKeyFactory>();
}

public class MyModelCacheKeyFactory : IModelCacheKeyFactory
{
    public object Create(DbContext context)
        =>  context.GetType();
}

public class Blog
{
    public int Id { get; set; }
    public string Name { get; set; }
}

roji avatar Apr 28 '22 09:04 roji

Was docced as part of dotnet/efcore#25154, but no sure if it is noted as a breaking changed.

ajcvickers avatar Apr 28 '22 09:04 ajcvickers

Thanks, missed that. Leaving open to see about adding a breaking change note.

roji avatar Apr 28 '22 09:04 roji

I got the same error when I created a DbContext and tried to invoke dbContext.Model.GetChangeTrackingStrategy(). I have not configured any IModelCacheKeyFactory. Using dbContext.GetService<IDesignTimeModel>().Model as recommended in the exception seemed to get around that exception but (a) I then got the exception when calling dbContext.Model.GetPropertyAccessMode(), and also (b) it requires using the Infrastructure namespace, which doesn't feel right for a user app.

sjb-sjb avatar May 09 '22 02:05 sjb-sjb

@sjb-sjb Why do you need to call dbContext.Model.GetChangeTrackingStrategy() and dbContext.Model.GetPropertyAccessMode()?

AndriySvyryd avatar May 09 '22 02:05 AndriySvyryd

Well, I want to check the caller’s configuration of the dbcontext to make sure it matches what my library requires.

sjb-sjb avatar May 13 '22 11:05 sjb-sjb

Poaching

ajcvickers avatar Sep 21 '22 12:09 ajcvickers