Чередование между несколькими моделями с одинаковым типом DbContext

Встроенная OnModelCreating модель может использовать свойство в контексте, чтобы изменить способ построения модели. Например, предположим, что вы хотите настроить сущность по-разному на основе некоторых свойств:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    if (UseIntProperty)
    {
        modelBuilder.Entity<ConfigurableEntity>().Ignore(e => e.StringProperty);
    }
    else
    {
        modelBuilder.Entity<ConfigurableEntity>().Ignore(e => e.IntProperty);
    }
}

К сожалению, этот код не будет работать как есть, так как EF создает модель и выполняется OnModelCreating только один раз, кэширование результата по причинам производительности. Однако вы можете подключиться к механизму кэширования модели, чтобы сделать EF осведомленным о свойстве, производящим различные модели.

IModelCacheKeyFactory

EF используется IModelCacheKeyFactory для создания ключей кэша для моделей. По умолчанию EF предполагает, что для любого заданного типа контекста модель будет одинаковой, поэтому реализация по умолчанию этой службы возвращает ключ, содержащий только тип контекста. Чтобы создать разные модели из одного типа контекста, необходимо заменить IModelCacheKeyFactory службу правильной реализацией. Созданный ключ будет сравниваться с другими ключами модели с помощью Equals метода, учитывая все переменные, влияющие на модель.

Следующая реализация учитывается UseIntProperty при создании ключа кэша модели:

public class DynamicModelCacheKeyFactory : IModelCacheKeyFactory
{
    public object Create(DbContext context, bool designTime)
        => context is DynamicContext dynamicContext
            ? (context.GetType(), dynamicContext.UseIntProperty, designTime)
            : (object)context.GetType();
}

Кроме того, необходимо реализовать перегрузку метода Create, который также обрабатывает кэширование модели во время разработки. Как показано в следующем примере:

public class DynamicModelCacheKeyFactoryDesignTimeSupport : IModelCacheKeyFactory
{
    public object Create(DbContext context, bool designTime)
        => context is DynamicContext dynamicContext
            ? (context.GetType(), dynamicContext.UseIntProperty, designTime)
            : (object)context.GetType();

    public object Create(DbContext context)
        => Create(context, false);
}

Наконец, зарегистрируйте новое IModelCacheKeyFactory в контексте OnConfiguring:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseInMemoryDatabase("DynamicContext")
        .ReplaceService<IModelCacheKeyFactory, DynamicModelCacheKeyFactory>();

Дополнительные сведения см. в полном примере проекта .