43

展開プロセスをクリーンアップするために、移行を検討しています。変更を本番環境にプッシュするときに必要な手動介入が少ないほど、より良い結果が得られます。

移行システムで 3 つの大きな障害に遭遇しました。それらを回避するきれいな方法を見つけられない場合、それらはショーストッパーです。

1. 移行ごとにシード データを追加するにはどうすればよいですか。

「add-migration」コマンドを実行して、Up および Down 機能を備えた新しい移行ファイルを足場にします。ここで、Up と Down の両方の変更でデータを自動的に変更したいと考えています。シード データを Configuration.Seed メソッドに追加したくありません。これは、あらゆる種類の重複の問題で終了するすべての移行に対して実行されるためです。

2. 上記が不可能な場合、重複を避けるにはどうすればよいですか?

データベースに値を追加するためにループする列挙型があります。

foreach(var enumValue in Enum.GetValues(typeof(Access.Level)))
{
    context.Access.AddOrUpdate(
        new Access { AccessId = ((int)enumValue), Name = enumValue.ToString() }
    );
}
context.SaveChanges();

AddOrUpdate を使用していますが、データベースに重複があります。上記のコードは、3番目の最後の問題に私をもたらします:

3. 主キーをシードするにはどうすればよいですか?

上記のコードで列挙可能なものは次のとおりです。

public class Access
{
    public enum Level
    {
        None = 10,
        Read = 20,
        ReadWrite = 30
    }
    public int AccessId { get; set; }
    public string Name { get; set; }
}

主キーとして必要な値を指定していますが、Entity Framework はそれを無視しているようです。それらはまだ 1,2,3 になります。10,20,30 にするにはどうすればよいですか?

現時点での EF のこれらの制限はありますか、それとも私が見ていない他の種類の大惨事を防ぐための意図的な制約ですか?

4

4 に答える 4

29
  1. 移行で挿入したいデータを修正したら、への呼び出しを使用して Up() 移行に直接挿入しますSql("Insert ...")。このページの途中にあるメモを参照してください:固定データの挿入方法
  2. 自然キーを指定する識別子式を取る AddOrUpdate オーバーロードを呼び出すことにより、シード メソッドでの重複を防ぎます。この回答このブログ エントリを参照してください。
  3. 整数である主キーは、デフォルトで ID フィールドとして作成されます。それ以外を指定するには、[DatabaseGenerated(DatabaseGeneratedOption.None)]属性を使用します

これはInitializer と Seed メソッドの良い説明だと思います

AddOrUpdate メソッドの使用例を次に示します。

foreach(var enumValue in Enum.GetValues(typeof(Access.Level)))
{
    context.Access.AddOrUpdate(
        x => x.Name, //the natural key is "Name"
        new Access { AccessId = ((int)enumValue), Name = enumValue.ToString() }
    );
}
于 2013-09-12T16:23:09.797 に答える
3

OK、少しバッシングして、EF をサブミッションにバッシングすることができました。これが私がしたことです:

1.特定の移行のデータを確認する方法がありません。すべて共通の Configuration.Seed メソッドに入れる必要があります。

2.重複を避けるために、2つのことをしなければなりませんでした。列挙型については、次のシード コードを記述しました。

foreach (var enumValue in Enum.GetValues(typeof(Access.Level)))
{
    var id = (int)enumValue;
    var val = enumValue.ToString();

    if(!context.Access.Any(e => e.AccessId == id))
        context.Access.Add(
            new Access { AccessId = id, Name = val }
        );
}
context.SaveChanges();

基本的に、存在するかどうかを確認し、存在しない場合は追加するだけです

3.上記が機能するためには、主キー値を挿入できる必要があります。幸いなことに、このテーブルには常に同じ静的データが含まれているため、自動インクリメントを無効にすることができました。これを行うには、コードは次のようになります。

public class Access
{
    public enum Level
    {
        None = 10,
        Read = 20,
        ReadWrite = 30
    }

    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int AccessId { get; set; }
    public string Name { get; set; }
}
于 2013-09-12T13:35:21.877 に答える
3

こんにちは、このリンクであなたの問題に関する非常に役立つ情報を見つけました: Safari Books Online

「1. 移行ごとにシード データを追加するにはどうすればよいですか?」 例でわかるように、シード用の新しい構成を作成する必要があります。このシード構成は、移行後に呼び出す必要があります。

public sealed class Configuration : DbMigrationsConfiguration
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
    }

    protected override void Seed(SafariCodeFirst.SeminarContext context)
    {
        //  This method will be called after migrating to the latest version.

        //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
        //  to avoid creating duplicate seed data. E.g.
        //
        //    context.People.AddOrUpdate(
        //      p => p.FullName,
        //      new Person { FullName = "Andrew Peters" },
        //      new Person { FullName = "Brice Lambson" },
        //      new Person { FullName = "Rowan Miller" }
        //    );
        //
    }
}

「2. 上記が不可能な場合、重複を避けるにはどうすればよいですか?」

AddOrUpdateここでエラーが発生した場合は、重複を回避するのに正確に役立つ必要があります。コールスタックのポストに構成エラーがある可能性があります。例を見てください!

「3.主キーをシードするにはどうすればよいですか?」

ここでは、キー定義にもあります。あなたよりもあなたの鍵なら、DatabaseGenerated(DatabaseGeneratedOption.Identity)それを提供する必要はありません。他のいくつかのシナリオでは、キーの種類に応じて新しいシナリオを作成する必要があります。

「現時点での EF のこれらの制限はありますか?それとも、私が目にしていない他の種類の大災害を防ぐための意図的な制約ですか?」
私が知っているわけではありません!

于 2013-09-12T09:30:01.157 に答える