具有相同 DbContext 類型的多個模型之間交替Alternating between multiple models with the same DbContext type

內建模型OnModelCreating內容無法使用的屬性來變更模型的建置方式。The model built in OnModelCreating could use a property on the context to change how the model is built. 比方說它無法用來排除特定的屬性:For example it could be used to exclude a certain property:

public class DynamicContext : DbContext
{
    public bool? IgnoreIntProperty { get; set; }

    public DbSet<ConfigurableEntity> Entities { get; set; }

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

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        if (IgnoreIntProperty.HasValue)
        {
            if (IgnoreIntProperty.Value)
            {
                modelBuilder.Entity<ConfigurableEntity>().Ignore(e => e.IntProperty);
            }
            else
            {
                modelBuilder.Entity<ConfigurableEntity>().Ignore(e => e.StringProperty);
            }
        }
    }
}

IModelCacheKeyFactoryIModelCacheKeyFactory

不過如果您嘗試這樣做而不需要額外的變更會得到相同的模型每次在新的內容建立的任何值IgnoreIntPropertyHowever if you tried doing the above without additional changes you would get the same model every time a new context is created for any value of IgnoreIntProperty. 這種情形因模型快取以改善效能,藉由只叫用 EF 所使用的機制OnModelCreating一次,快取模型。This is caused by the model caching mechanism EF uses to improve the performance by only invoking OnModelCreating once and caching the model.

根據預設 EF 會假設為任何指定的內容類型的模型將會相同。By default EF assumes that for any given context type the model will be the same. 若要這麼做的預設實作IModelCacheKeyFactory傳回只包含內容類型的金鑰。To accomplish this the default implementation of IModelCacheKeyFactory returns a key that just contains the context type. 若要變更此您需要更換IModelCacheKeyFactory服務。To change this you need to replace the IModelCacheKeyFactory service. 新的實作必須使用其他模型索引鍵傳回物件可比較Equals會考量會影響模型的所有變數的方法:The new implementation needs to return an object that can be compared to other model keys using the Equals method that takes into account all the variables that affect the model:

public class DynamicModelCacheKeyFactory : IModelCacheKeyFactory
{
    public object Create(DbContext context)
    {
        if (context is DynamicContext dynamicContext)
        {
            return (context.GetType(), dynamicContext.IgnoreIntProperty);
        }
        return context.GetType();
    }
}