内置 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>();
有关更多上下文,请参阅 完整的示例项目 。