在具有相同 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);
    }
}

遗憾的是,此代码在 as-is不起作用,因为 EF 生成模型并仅运行 OnModelCreating 一次,因此出于性能原因缓存结果。 但是,可以挂钩到模型缓存机制中,使 EF 能够识别生成不同模型的属性。

IModelCacheKeyFactory

EF 使用 IModelCacheKeyFactory 为模型生成缓存密钥;默认情况下,EF 假定对于任何给定的上下文类型,模型将相同,因此此服务的默认实现返回仅包含上下文类型的密钥。 若要从同一上下文类型生成不同的模型,需要将服务替换为 IModelCacheKeyFactory 正确的实现;生成的密钥将使用该方法与其他模型键 Equals 进行比较,同时考虑影响模型的所有变量。

以下实现,在生成模型缓存密钥时将 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);
}

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

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

有关更多上下文,请参阅 完整的示例项目