簡體   English   中英

實體框架自動更新

[英]Entity-Framework auto update

我嘗試在我的項目中實現實體框架! 我的項目基於插件,因此我不知道必須將哪個對象保存到數據庫。

我已經實現了它:

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”上下文的模型已更改。 考慮使用Code First Migrations更新數據庫( 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)

編輯2:

  <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 ,以便他們可以使用Fluent API自己配置其實體類型。

跑:

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要求DbSet位於上下文類中,因此您需要動態生成(基於插件實體) DatabaseContext類,對其進行編譯和加載。 之后,您可以開始考慮遷移(自動遷移或手動遷移,是否允許數據丟失等)。
同樣,使用剛剛創建的DatabaseContext應該很簡單(您應該能夠通過標准DbContext接口執行對類的所有訪問)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM