实体框架自动更新 [英] Entity-Framework auto update
问题描述
我已经实现了它:
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屋!