简体   繁体   English

实体框架自动更新

[英]Entity-Framework auto update

i try to implement Entity-Framework into my project! 我尝试在我的项目中实现实体框架! My Project is plugin-based so i do not know which object i have to save to database. 我的项目基于插件,因此我不知道必须将哪个对象保存到数据库。

I have implemented it so: 我已经实现了它:

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);
    }

}

But i get this exception, when i give a change: 但是当我进行更改时,出现此异常:

The model backing the 'DatabaseContext' context has changed since the database was created. 自创建数据库以来,支持“ DatabaseContext”上下文的模型已更改。 Consider using Code First Migrations to update the database ( http://go.microsoft.com/fwlink/?LinkId=238269 ). 考虑使用Code First Migrations更新数据库( http://go.microsoft.com/fwlink/?LinkId=238269 )。

This error is completly logical. 此错误完全是逻辑上的。 The database is out of sync, but how i will get the update? 数据库不同步,但是我将如何获取更新? i Have read something about this: 我已经阅读了一些有关此的内容:

 var config = new DbMigrationsConfiguration<MyContext> { AutomaticMigrationsEnabled = true };
 var migrator = new DbMigrator(config);
 migrator.Update();

But i don't know how and where to use it correctly! 但是我不知道如何正确使用它! Thank you very much! 非常感谢你!

EDIT1: When i try to: Enable-Migrations –EnableAutomaticMigrations EDIT1:当我尝试执行以下操作:Enable-Migrations –EnableAutomaticMigrations

I got this error: 我收到此错误:

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)

EDIT2: 编辑2:

  <connectionStrings>
    <add name="DatabaseContext" providerName="System.Data.SqlServerCe.4.0" connectionString="Data Source=SOM_db.sdf;Max Database Size=1024" />
  </connectionStrings>

What are you asking for is doable, but with some limitations. 您要求的是可行的,但有一些限制。

Solution: 解:

First, remove the 首先,删除

Database.Initialize(true);

from the constructor. 来自构造函数。 The constructor is called multiple times, including the migrations. 多次调用构造函数, 包括迁移。

Second, create a configuration class like this 其次,创建一个这样的配置类

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

Then change the constructor as follows: 然后按如下所示更改构造函数:

public DataContext()
{
    Database.SetInitializer(new MigrateDatabaseToLatestVersion<DataContext, DataContextConfiguration>());
}

and you are done. 到此为止。 The database tables for the entity types from the plugins will be automatically created/updated accordingly. 来自插件的实体类型的数据库表将相应地自动创建/更新。

To recap, basically this is a standard Code First approach with automatic migrations enabled, but with dynamic entity type registration/configuration from inside the OnModelCreating override. 概括地说,这基本上是一种标准的“代码优先”方法,该方法启用了自动迁移,但是从OnModelCreating覆盖内部进行了动态实体类型注册/配置。

Limitations: 局限性:

  • If you don't set AutomaticMigrationDataLossAllowed = true , when the existing plugin is removed, EF will generate exception because it is not allowed to delete the corresponding tables. 如果您未设置AutomaticMigrationDataLossAllowed = true ,则在删除现有插件时,EF将生成异常,因为不允许删除相应的表。 And if you do so, the plugin tables will be deleted, so if the plugin is added again, it will start from zero. 如果这样做,插件表将被删除,因此,如果再次添加插件,它将从零开始。

  • The plugin entities can only be configured using Data Annotations. 插件实体只能使用数据注释进行配置。 If you want to give them full control, you'd probably need to change the plugin interface and instead of taking the entity types, to call some method and pass the DbModelBuilder instead, so they can use Fluent API to configure their entity types themselves. 如果要完全控制它们,则可能需要更改插件接口,而不是采用实体类型,而是调用某些方法并传递DbModelBuilder ,以便他们可以使用Fluent API自己配置其实体类型。

Run: 跑:

Update-Database –Verbose

If it fails, please paste the messages as a comment. 如果失败,请粘贴消息作为注释。

public class myContext : DbContext
{
    public DbSet<myTable> myTables { get; set; }

    public myContext() : base("myConStr") { }

    public void UpdateDatabase()
    {
        var Migrator = new DbMigrator(new Migrations.Configuration(){ TargetDatabase = new DbConnectionInfo(this.Database.Connection.ConnectionString, "System.Data.SqlClient") });
        IEnumerable<string> PendingMigrations = Migrator.GetPendingMigrations();
        foreach (var Migration in PendingMigrations)
            Migrator.Update(Migration);
    }
}

static void Main(string[] args)
{
   var db = new myContext();
   db.UpdateDatabase();
}

I don't think that it will ever work with EF6 using this approach. 我认为使用这种方法无法在EF6中使用。

EF needs that the DbSets are on the context class so you need to generate your DatabaseContext class on the fly (basing on plugin entities), compile and load it. EF要求DbSet位于上下文类中,因此您需要动态生成(基于插件实体) DatabaseContext类,对其进行编译和加载。 After that you can start thinking about migration (automatic or manual, with or without allowing data lossing and so on). 之后,您可以开始考虑迁移(自动迁移或手动迁移,是否允许数据丢失等)。
Also using your just created DatabaseContext should be simple (you should be able to do everything accessing to your class via standard DbContext interface) 同样,使用刚刚创建的DatabaseContext应该很简单(您应该能够通过标准DbContext接口执行对类的所有访问)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM