实体框架自动更新 [英] Entity-Framework auto update

查看:150
本文介绍了实体框架自动更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图将Entity-Framework实现到我的项目中!我的项目是基于插件的,所以我不知道我要保存到数据库的对象。



我已经实现了它:

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

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
foreach(BackendContext.Current.PluginManager._plugins中的PluginDto插件){
foreach(在plugin.plugin.getPluginDatabaseObjects()中键入obj)
{
Type typ = typeof(EntityTypeConfiguration&); MakeGenericType(obj);

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

}

但是我得到这个例外我修改了:



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


这个错误是完全合乎逻辑的。数据库不同步,但是如何获得更新?我已经阅读了一些这样的信息:

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

但我不知道如何和在哪里正确使用它!
非常感谢!



EDIT1:
当我尝试:启用迁移 - 启用自动移动



我收到此错误:

  System.NullReferenceException:对象引用未设置为对象的实例。 C:\Users\Flo\Documents\Visual Studio 2015/\\Projects\SOM\Backend\BackendService\BackendService中的SOM.Backend.database.DatabaseContext.OnModelCreating(DbModelBuilder modelBuilder)中的
\database\DatabaseContext.cs:line 26
在System.Data.Entity.Internal.LazyInternalContext.CreateModelBuilder()
在System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)$在System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput输入)中的
在System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
在System.Data.Entity。 Internal.LazyInternalContext.MarkDatabaseInitialized()
在System.Data.Entity.Database.Initialize(Boolean force)
在SOM.Backend.database.DatabaseContext..ctor()在C:\Users\ Flo\\ \\ Documents and Settings xt.cs:line 21
---从抛出异常的前一个位置的堆栈跟踪结束--- System b。 Data.Entity.Infrastructure.DbContextInfo.CreateInstance()
在System.Data.Entity.Infrastructure.DbContextInfo..ctor(类型contextType,DbProviderInfo modelProviderInfo,AppConfig配置,DbConnectionInfo connectionInfo,Func`1解析器)
在System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration配置,DbContext usersContext,DatabaseExistenceState existsState,Boolean calledByCreateDatabase)
在System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration配置)
在System.Data.Entity.Migrations.Design.MigrationScaffolder..ctor(DbMigrationsConfiguration migrationsConfiguration)
在System.Data.Entity.Migrations.Design.ToolingFacade.ScaffoldRunner.Run()
在System.AppDomain .DoCallBack(CrossAppDomainDelegate callBa c.Delegate)
在System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
在System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner转轮)
在System.Data.Entity.Migrations .Design.ToolingFacade.ScaffoldInitialCreate(String language,String rootNamespace)
在System.Data.Entity.Migrations.EnableMigrationsCommand。  c__DisplayClass2。< .ctor> b__0()
在System.Data .Entity.Migrations.MigrationsDomainCommand.Execute(Action command)

EDIT2:

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


解决方案

你要求什么是可行的,



解决方案:



首先,删除

  Database.Initialize(true); 

从构造函数。构造函数被多次调用,包括迁移。



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

 内部密封类DataContextConfiguration:DbMigrationsConfiguration< DataContext> 
{
public DataContextConfiguration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
ContextKey =DataContext;
}
}

然后更改构造函数如下:

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

你完成了从插件中实体类型的数据库表将被相应地自动创建/更新。



要概述,基本上这是一个标准的Code First方法,启用了自动迁移,但是从 OnModelCreating 覆盖内的动态实体类型注册/配置。



限制:




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


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



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. Consider using Code First Migrations to update the database (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

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:

  <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.

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. 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.

这篇关于实体框架自动更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆