列を追加してテーブルをドロップしないEFコードのカスタム初期化戦略
-
24-10-2019 - |
質問
最新のEFコードFirst Nugetパッケージには、のカスタム実装が付属しています IDatabaseInitializer
呼び出されました DontDropDbJustCreateTablesIfModelChanged
. 。名前が示すように、モデルの変更が検出された場合、データベース全体をドロップして再作成することはなく、テーブルをドロップして再現するだけです。
私はこのモデルクラスを持っているとします:
public class User
{
public string Username { get; set; }
// This property is new; the model has changed!
public string OpenID { get; set; }
}
どのように実装しますか IDatabaseInitializer
それ テーブルもドロップしません. 。この場合、それはただ追加します OpenID
ユーザーテーブルへの列?
解決
SQLの問題だと思います。したがって、SQL Serverの場合は次のようなものを書くことができます。
public class MyInitializer : IDatabaseInitializer<MyContext>
{
public void InitializeDatabase(MyContext context)
{
context.Database.SqlCommand(
@"
IF NOT EXISTS (SELECT 1 FROM sys.columns AS col
INNER JOIN sys.tables AS tab ON tab.object_Id = col.object_Id
WHERE tab.Name = 'User' AND col.Name = 'OpenId')
BEGIN
ALTER TABLE dbo.User ADD OpenId INT;
END");
}
}
しかし、同じように、そのようなスクリプトをアプリケーションに追加せずに実行することができます。
他のヒント
最初にCodeの現在のバージョンを使用すると、スキーマを修正してテーブルにあるデータを保存することはできません。このリリースで参照データ /ルックアップテーブルなどのデータを維持することが重要である場合、独自の初期イザーを作成し、シードメソッドをオーバーライドしてテーブルを入力できます。
public class MyDbInitializer : DropCreateDatabaseIfModelChanges<MyContext>
{
protected override void Seed(MyContext context)
{
var countries = new List<Country>
{
new Country {Id=1, Name="United Kingdom"},
new Country{Id=2, Name="Ireland"}
};
countries.ForEach(c => context.Countries.Add(c));
}
}
そして、これをapplication_startで使用します。
Database.SetInitializer<MyContext>(new MyDbInitializer());
これは現在EFチームによって対処されていると思いますが、コードの最初のドロップが発表された時点ではリリースの準備ができていませんでした。ここでプレビューを見ることができます: 最初の移行をコードします
所属していません StackOverflow