Leer en inglés

Compartir a través de


Alternar entre varios modelos con el mismo tipo DbContext

El modelo integrado en OnModelCreating puede usar una propiedad en el contexto para cambiar cómo se compila el modelo. Por ejemplo, supongamos que quería configurar una entidad de forma diferente en función de alguna propiedad:

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

Desafortunadamente, este código no funcionaría tal cual, ya que EF compila el modelo y ejecuta OnModelCreating solo una vez, almacenando en caché el resultado por motivos de rendimiento. Sin embargo, puede enlazar con el mecanismo de almacenamiento en caché del modelo para que EF tenga en cuenta la propiedad que produce diferentes modelos.

IModelCacheKeyFactory

EF usa IModelCacheKeyFactory para generar claves de caché para los modelos; de forma predeterminada, EF supone que para cualquier tipo de contexto determinado, el modelo será el mismo, por lo que la implementación predeterminada de este servicio devuelve una clave que solo contiene el tipo de contexto. Para generar modelos diferentes del mismo tipo de contexto, debe reemplazar el servicio IModelCacheKeyFactory por la implementación correcta; la clave generada se comparará con otras claves de modelo mediante el método Equals, teniendo en cuenta todas las variables que afectan al modelo.

La siguiente implementación tiene en cuenta UseIntProperty al generar una clave de caché del modelo:

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

También tiene que implementar la sobrecarga del método Create que también controla el almacenamiento en caché del modelo en tiempo de diseño. Como en el ejemplo siguiente:

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 último, registre el nuevo IModelCacheKeyFactory en el OnConfiguring del contexto:

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

Vea el proyecto de ejemplo completo para obtener más contexto.