Compartilhar via


Alternar entre vários modelos com o mesmo tipo DbContext

O modelo construído em OnModelCreating pode usar uma propriedade no contexto para alterar a forma como o modelo é construído. Por exemplo, suponha que você queria configurar uma entidade de forma diferente com base em alguma propriedade:

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

Infelizmente, esse código não funcionaria as-is, já que o EF cria o modelo e é executado OnModelCreating apenas uma vez, armazenando o resultado em cache por motivos de desempenho. No entanto, você pode conectar-se ao mecanismo de cache de modelo para tornar o EF ciente da propriedade que produz modelos diferentes.

IModelCacheKeyFactory

O EF usa a IModelCacheKeyFactory opção para gerar chaves de cache para modelos; por padrão, o EF pressupõe que, para qualquer tipo de contexto, o modelo será o mesmo, portanto, a implementação padrão desse serviço retorna uma chave que contém apenas o tipo de contexto. Para produzir modelos diferentes do mesmo tipo de contexto, você precisa substituir o IModelCacheKeyFactory serviço pela implementação correta; a chave gerada será comparada com outras chaves de modelo usando o Equals método, levando em conta todas as variáveis que afetam o modelo.

A implementação a seguir leva o UseIntProperty em conta ao produzir uma chave de cache de modelo.

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

Você também precisa implementar a sobrecarga do método Create que lida com o cache de modelo em tempo de design. Como no exemplo a seguir:

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);
}

Por fim, registre seu novo IModelCacheKeyFactory no contexto OnConfiguring:

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

Consulte o projeto de exemplo completo para obter mais contexto.