交替執行多個模型與 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. 這因為模型快取的機制來改善效能,藉由只叫用使用 EFOnModelCreating一次和快取模型。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();
    }
}