私の自転車Entity FrameWork、自動移行、保存データ付き

私は自転車が大好きです。



EFを使用してソフトウェアを作成するプロセスでは、構造が頻繁に変更され、問題が発生します。 バージョン4.3より前は、データベースがデータ損失とテストデータベースで満たされる必要がある状態で再作成されました。

バージョン4.3以降。 移行が登場しました。 移行により、すべてのデータが削除され、頭痛の種が軽減されました。 しかし、データベースの更新メカニズムについては手動で説明します。2回の移行後はうんざりです。 自動移行が必要です。 1つのマイナス、構造の大幅な変更(フィールドタイプ、1つのテーブルから別のテーブルへのフィールド)-データが失われます。

その結果、自転車が登場しました。

データベースの構造を変更するとき。

1.最後の更新からのバージョンを定義します。

2.データベースをSQLサーバーから切断します。

3.データベースファイルをコピーします(オリジナルの隣)FILEBD-> FILEBD_VERSION;

4.オリジナルを古い名前で添付します。

5. OLD。VERSIONという名前でコピーを添付します。

6.自動移行を適用します。

7.バージョンを書き留めます。



私にとっての主な利点:

1.質問なしで構造を更新します。

2.すでに手動でドラッグできる蓄積データの安全性(T-SQLを恐れていません:))



public class RenameCreateDatabaseIfModelChanged<TContext> : IDatabaseInitializer<TContext> where TContext : System.Data.Entity.DbContext { public void InitializeDatabase(TContext context) { int version = 1; DbCommand cmd; if (context.Database.Exists()) { bool throwIfNoMetadata = true; if (context.Database.CompatibleWithModel(throwIfNoMetadata)) { return; } DbDataReader dr; context.Database.Connection.Open(); //GET VERSION cmd = context.Database.Connection.CreateCommand(); cmd.CommandText = "SELECT TOP 1 * FROM sysobjects WHERE xtype='U' AND name = '__ase.version'"; dr = cmd.ExecuteReader(); if (dr.Read()) { //VERSION EXISTS dr.Close(); cmd.CommandText = "SELECT TOP 1 Vesion FROM [__ase.version] ORDER BY CreatedOn DESC"; dr = cmd.ExecuteReader(); if (dr.Read()) version = (int)dr["Vesion"]; dr.Close(); version++; } else { //First dr.Close(); cmd.CommandText = "CREATE TABLE [__ase.version] ([Vesion] [int] NOT NULL, [CreatedOn] [datetime] NOT NULL)"; cmd.ExecuteNonQuery(); //WriteVersion(context, version); } //Get list files List<string> files = new List<string>(); cmd.CommandText = "EXEC SP_HELPFILE"; dr = cmd.ExecuteReader(); while (dr.Read()) { files.Add(dr["filename"].ToString()); } dr.Close(); //Disconnect all connections cmd.CommandText = String.Format("ALTER DATABASE [{0}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE", context.Database.Connection.Database); cmd.ExecuteNonQuery(); cmd.CommandText = String.Format("ALTER DATABASE [{0}] SET MULTI_USER WITH ROLLBACK IMMEDIATE", context.Database.Connection.Database); cmd.ExecuteNonQuery(); string dbName = context.Database.Connection.Database; //Deattach database cmd.CommandText = String.Format("USE MASTER; EXEC SP_DETACH_DB [{0}]", dbName); cmd.ExecuteNonQuery(); //Copy database string sql_file_old = String.Format("EXEC SP_ATTACH_DB [{0}], ", dbName); string sql_file_new = String.Format("EXEC SP_ATTACH_DB [{0}.{1}], ", dbName, version); foreach (string file in files) { File.Copy(file, file + "_" + version); sql_file_old += "'" + file + "', "; sql_file_new += "'" + file + "_" + version + "', "; } //Attach database cmd.CommandText = sql_file_old.Substring(0, sql_file_old.Length - 2); cmd.ExecuteNonQuery(); //Attach copy database cmd.CommandText = sql_file_new.Substring(0, sql_file_new.Length - 2); cmd.ExecuteNonQuery(); context.Database.Connection.Close(); } //Migrate with data loss var configuration = new DbMigrationsConfiguration<TContext>(); configuration.AutomaticMigrationDataLossAllowed = true; configuration.AutomaticMigrationsEnabled = true; var migrator = new DbMigrator(configuration); migrator.Update(); //Update version context.Database.Connection.Open(); cmd = context.Database.Connection.CreateCommand(); DbParameter param = cmd.CreateParameter(); param.ParameterName = "@v1"; param.Value = version; cmd.Parameters.Add(param); param = cmd.CreateParameter(); param.ParameterName = "@v2"; param.Value = DateTime.Now; cmd.Parameters.Add(param); cmd.CommandText = "INSERT INTO [__ase.version] ([Vesion], [CreatedOn]) VALUES (@v1, @v2)"; cmd.ExecuteNonQuery(); context.Database.Connection.Close(); } protected virtual void Seed(TContext context) { } } public class InitData : RenameCreateDatabaseIfModelChanged<AppEntities> { protected override void Seed(AppEntities context) { base.Seed(context); } } System.Data.Entity.Database.SetInitializer<AppEntities>(new InitData());
      
      






All Articles