实体框架自动更新

Flo*_*Flo 9 c# plugins entity-framework dynamic

我尝试将Entity-Framework实现到我的项目中!我的项目是基于插件的,所以我不知道我必须保存到数据库的哪个对象.

我已经实现了它:

public class DatabaseContext : DbContext
{
    public DatabaseContext() : base()
    {
        Database.Initialize(true);
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        foreach( PluginDto plugin in BackendContext.Current.PluginManager._plugins) {
            foreach(Type obj in plugin.plugin.getPluginDatabaseObjects())
            {
                Type typ = typeof(EntityTypeConfiguration<>).MakeGenericType(obj);

                List<MethodInfo> l = modelBuilder.GetType().GetMethods().ToList<MethodInfo>();

                MethodInfo m_Entitiy = modelBuilder.GetType().GetMethod("Entity").MakeGenericMethod(new Type[] { obj });
                var configObj = m_Entitiy.Invoke(modelBuilder, null);

                MethodInfo m_ToTable = configObj.GetType().GetMethod("ToTable", new Type[] { typeof(String) });
                m_ToTable.Invoke(configObj, new object [] { obj.Name }); 
            }
        }

        base.OnModelCreating(modelBuilder);
    }

}
Run Code Online (Sandbox Code Playgroud)

但是当我做出改变时,我得到了这个例外:

自创建数据库以来,支持"DatabaseContext"上下文的模型已更改.请考虑使用"代码优先迁移"来更新数据库(http://go.microsoft.com/fwlink/?LinkId=238269).

此错误完全符合逻辑.数据库不同步,但我将如何获得更新?我读过这个:

 var config = new DbMigrationsConfiguration<MyContext> { AutomaticMigrationsEnabled = true };
 var migrator = new DbMigrator(config);
 migrator.Update();
Run Code Online (Sandbox Code Playgroud)

但我不知道如何以及在何处正确使用它!非常感谢你!

编辑1:当我尝试:启用 - 迁移-EnableAutomaticMigrations

我收到了这个错误:

System.NullReferenceException: Object reference not set to an instance of an object.
   at SOM.Backend.database.DatabaseContext.OnModelCreating(DbModelBuilder modelBuilder) in C:\Users\Flo\Documents\Visual Studio 2015\Projects\SOM\Backend\BackendService\BackendService\database\DatabaseContext.cs:line 26
   at System.Data.Entity.Internal.LazyInternalContext.CreateModelBuilder()
   at System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
   at System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input)
   at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
   at System.Data.Entity.Internal.LazyInternalContext.MarkDatabaseInitialized()
   at System.Data.Entity.Database.Initialize(Boolean force)
   at SOM.Backend.database.DatabaseContext..ctor() in C:\Users\Flo\Documents\Visual Studio 2015\Projects\SOM\Backend\BackendService\BackendService\database\DatabaseContext.cs:line 21
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Data.Entity.Infrastructure.DbContextInfo.CreateInstance()
   at System.Data.Entity.Infrastructure.DbContextInfo..ctor(Type contextType, DbProviderInfo modelProviderInfo, AppConfig config, DbConnectionInfo connectionInfo, Func`1 resolver)
   at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration, DbContext usersContext, DatabaseExistenceState existenceState, Boolean calledByCreateDatabase)
   at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration)
   at System.Data.Entity.Migrations.Design.MigrationScaffolder..ctor(DbMigrationsConfiguration migrationsConfiguration)
   at System.Data.Entity.Migrations.Design.ToolingFacade.ScaffoldRunner.Run()
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner)
   at System.Data.Entity.Migrations.Design.ToolingFacade.ScaffoldInitialCreate(String language, String rootNamespace)
   at System.Data.Entity.Migrations.EnableMigrationsCommand.<>c__DisplayClass2.<.ctor>b__0()
   at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)
Run Code Online (Sandbox Code Playgroud)

EDIT2:

  <connectionStrings>
    <add name="DatabaseContext" providerName="System.Data.SqlServerCe.4.0" connectionString="Data Source=SOM_db.sdf;Max Database Size=1024" />
  </connectionStrings>
Run Code Online (Sandbox Code Playgroud)

Iva*_*oev 9

你要求的是可行的,但有一些限制.

解:

首先,删除

Database.Initialize(true);
Run Code Online (Sandbox Code Playgroud)

来自构造函数.构造函数被多次调用,包括迁移.

其次,创建一个这样的配置类

internal sealed class DataContextConfiguration : DbMigrationsConfiguration<DataContext>
{
    public DataContextConfiguration()
    {
        AutomaticMigrationsEnabled = true;
        AutomaticMigrationDataLossAllowed = true;
        ContextKey = "DataContext";
    }
}
Run Code Online (Sandbox Code Playgroud)

然后更改构造函数,如下所示:

public DataContext()
{
    Database.SetInitializer(new MigrateDatabaseToLatestVersion<DataContext, DataContextConfiguration>());
}
Run Code Online (Sandbox Code Playgroud)

你完成了 将自动创建/更新插件中实体类型的数据库表.

回顾一下,基本上这是一个标准的Code First方法,启用了自动迁移,但是在OnModelCreating覆盖内部使用动态实体类型注册/配置.

限制:

  • 如果未设置AutomaticMigrationDataLossAllowed = true,则在删除现有插件时,EF将生成异常,因为不允许删除相应的表.如果你这样做,插件表将被删除,所以如果插件再次添加,它将从零开始.

  • 插件实体只能使用数据注释进行配置.如果你想给他们完全控制,你可能需要更改插件接口,而不是采用实体类型,调用一些方法并传递DbModelBuilder,所以他们可以使用Fluent API自己配置他们的实体类型.

  • 这就是我提到的一个问题。如果您不注册实体类型,EF 会假定它已被删除。如果您没有设置上述选项(默认情况下为“false”),则会出现异常。不幸的是,据我所知,没有选项可以让您保留现有的表。所以你要么得到全部,要么什么都没有:( (2认同)