实体框架自动更新

本文关键字:更新 框架 实体 | 更新日期: 2023-09-27 18:05:55

我尝试实现实体框架到我的项目!我的项目是基于插件的,所以我不知道我要保存到数据库的对象。

我已经实现了它:

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

但是我得到这个异常,当我给一个改变:

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

这个错误完全符合逻辑。数据库是不同步的,但我将如何得到更新?我读过一些关于这个的东西:

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

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

EDIT1:当我尝试:Enable-Migrations -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)

EDIT2:

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

实体框架自动更新

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

解决方案:

首先,删除
Database.Initialize(true);
构造函数中的

。构造函数被多次调用,包括迁移。其次,创建一个像这样的配置类

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

然后按如下方式修改构造函数:

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

,就完成了。来自插件的实体类型的数据库表将自动相应地创建/更新。

回顾一下,基本上这是一个标准的代码优先方法,启用了自动迁移,但是在OnModelCreating覆盖中使用了动态实体类型注册/配置。

限制:

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

  • 插件实体只能使用数据注释来配置。如果你想给他们完全的控制,你可能需要改变插件接口,而不是采取实体类型,调用一些方法和传递DbModelBuilder代替,所以他们可以使用流畅的API来配置自己的实体类型。

Run:

Update-Database –Verbose

如果失败,请将消息粘贴为评论

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

我不认为使用这种方法可以在EF6中工作。

EF需要DbSets在上下文类上,因此您需要动态生成DatabaseContext类(基于插件实体),编译并加载它。之后,您可以开始考虑迁移(自动或手动,允许或不允许数据丢失等)。
此外,使用您刚刚创建的DatabaseContext应该是简单的(您应该能够做的一切访问您的类通过标准DbContext接口)