在具有相同 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 假定对于任何给定的上下文类型,模型都相同,因此该服务的默认实现将返回仅包含上下文类型的键。 若要从同一上下文类型构建不同的模型,需要将服务替换为正确的实现;生成的键将使用 IModelCacheKeyFactoryEquals 方法与其他的模型键进行比较,同时考虑影响模型的所有变量。

以下实现在生成模型缓存键时考虑 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);
}

最后,在上下文的 OnConfiguring 中注册新的 IModelCacheKeyFactory

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

请参阅完整示例项目以了解更多上下文。