Чередование между несколькими моделями с одинаковым типом 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 осведомленным о свойстве, создающем различные модели.

имоделкачекэйфактори

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

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

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

Начиная с EF Core 6 необходимо реализовать перегрузку метода 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>();

См. полный пример проекта для получения дополнительных контекстов.