Compartir a través de


Alternar entre varios modelos con el mismo tipo DbContext

El modelo integrado 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 as-is, ya que EF compila el modelo y se ejecuta OnModelCreating solo una vez, almacenando en caché el resultado por motivos de rendimiento. Sin embargo, puede aprovechar el mecanismo de almacenamiento en caché del modelo para que EF reconozca cómo la propiedad genera 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 IModelCacheKeyFactory servicio por la implementación correcta; la clave generada se comparará con otras claves de modelo mediante el Equals método , teniendo en cuenta todas las variables que afectan al modelo.

La siguiente implementación tiene en cuenta el UseIntProperty cuando se produce una clave de caché 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();
}

También tiene que implementar la sobrecarga del método Create que también gestiona el almacenamiento en caché del modelo durante el 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 su nuevo IModelCacheKeyFactory en el contexto de su OnConfiguring:

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

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