实体框架:基于MEF找到的插件动态更改模型

时间:2016-05-27 08:23:33

标签: c# entity-framework mef

我正在开发一个应用程序,它可以通过使用MEF的插件进行扩展。该应用程序正在使用实体框架。上下文由工厂方法创建:

public class DataContextFactory
{
    [ImportingConstructor]
    public DataContextFactory([ImportMany] IEnumerable<IModelCreator> modelCreators, [Import(AllowDefault = true)]IDatabaseInitializer<DataContext> initializer)
    {
        ModelCreators = modelCreators;
        Initializer = initializer ?? new DefaultDataContextInitializer();
    }

    public DbContext Create()
    {
        return new DataContext(ModelCreators, Initializer);
    }
}


public interface IModelCreator
{
    void OnModelCreating(DbModelBuilder modelBuilder);
}

public class DataContext : DbContext
{
    public DataContext(IEnumerable<IModelCreator> modelCreators, IDatabaseInitializer<DataContext> initializer)
    {
        ModelCreators = modelCreators;
        if (initializer != null)
        {
            Database.SetInitializer(initializer);
        }
    }

    private IEnumerable<IModelCreator> ModelCreators { get; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

        foreach (var creator in ModelCreators)
        {
            creator.OnModelCreating(modelBuilder);
        }
    }
}

每个插件定义它自己的IModelCreator。 然后,实体将被`DbContext.Set()。

访问

问题是EF不会创建额外的表,它会丢弃数据库或抛出异常(取决于使用的初始化程序)。当我打开迁移时,我无法生成迁移,因为项目中没有DbContext所在的模型。

每个插件是否必须提供SQL脚本来创建它的表格,或者EF是否有办法在运行时为使用插件导入的实体添加表格?

如果我实现自己的IDatabaseInitializer,我怎么能告诉它创建丢失的表?

1 个答案:

答案 0 :(得分:1)

我使用了MigrateDatabaseToLatestVersion<TContext, TMigrationsConfiguration> Class

我创建了CompositeDataContextInitializer并更改了我的DataContextFactory,将其作为参数传递给我的DataContext

public class CompositedDataContextInitializer : MigrateDatabaseToLatestVersion<DataContext, Migrations.MigrationConfiguration>
{
    protected virtual void Seed(DataContext context)
    {
        if (context == null) throw new ArgumentNullException(nameof(context));
        foreach (var seeder in ServiceLocator.Current.GetAllInstances<IDataSeeder>())
        {
            seeder.Seed(context);
        }
    }
}


[Export(typeof(IDbContextFactory<DbContext>))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class ContextFromCompositionFactory : IDbContextFactory<DbContext>, IDbContextFactory<DataContext>
{
    public DbContext Create() => new DataContext(ServiceLocator.Current.GetAllInstances<IModelCreator>(), new CompositedDataContextInitializer());

    DataContext IDbContextFactory<DataContext>.Create() => (DataContext)Create();
}


public interface IModelCreator
{
    void OnModelCreating(DbModelBuilder modelBuilder);
}

public class DataContext : DbContext
{
    public DataContext(IEnumerable<IModelCreator> modelCreators, IDatabaseInitializer<DataContext> initializer)
    {
        ModelCreators = modelCreators;
        if (initializer != null)
        {
            Database.SetInitializer(initializer);
        }
    }

    private IEnumerable<IModelCreator> ModelCreators { get; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

        foreach (var creator in ModelCreators)
        {
            creator.OnModelCreating(modelBuilder);
        }
    }
}

TPT Inheritance仍然存在一些问题;如果要存储从系统中已有的类继承的新类,请使用TPH Inheritance