web-dev-qa-db-ja.com

Entity Framework Code Firstを使用してデータベースをシードするにはどうすればよいですか?

データベースは(テーブルと同様に)正常に作成されますが、シードされません。私は数時間を費やし、たくさんの記事を読みましたが、手に入れることができませんでした。助言がありますか?

補足として、クライアントでDatabaseContextへの参照を持たずに初期化子を呼び出すことは可能ですか?

考えられるすべての関連コードを含めました。他に何か役立つことがあれば、私に知らせてください。

私が試したもの:

  1. 接続文字列を削除しました(デフォルトはsqlexpressであるため、名前が変更されただけです)
  2. DropCreateDatabaseIfModelChangesをDropCreateDatabaseAlwaysに変更しましたが、それでも同じです。

編集:本当に奇妙なことは、それが一度働いたということですが、どうやってそれが再び壊れたのか分かりません。接続文字列を想定していますが、誰が知っています。

DatabaseInitializer.cs

public class DatabaseInitializer : DropCreateDatabaseIfModelChanges<DatabaseContext>
{
  protected override void Seed(DatabaseContext context)
  {
    // Seeding data here
    context.SaveChanges();
  }
}

DatabaseContext.cs

public class DatabaseContext : DbContext
{
  protected override void OnModelCreating(DbModelBuilder mb)
  {
    // Random mapping code
  }

  public DbSet<Entity1> Entities1 { get; set; }
  public DbSet<Entity2> Entities2 { get; set; }

}

Global.asax.cs-Application_Start()

protected void Application_Start()
{
  Database.SetInitializer<DatabaseContext>(new DatabaseInitializer());
  AreaRegistration.RegisterAllAreas();
  RegisterGlobalFilters(GlobalFilters.Filters);
  RegisterRoutes(RouteTable.Routes);
}

クライアントweb.config

<connectionStrings>
  <add name="DatabaseContext" connectionString="data source=.\SQLEXPRESS;Database=Database;Integrated Security=SSPI;" providerName="System.Data.SqlClient" />
</connectionStrings>

溶液

ドキュメントのために、ここでソリューションを共有しています。とにかくすべてのコメントをナビゲートするのは苦痛です。結局、DatabaseInitializerとDatabaseContextは別々のクラスにありました。これらの小さな変更がそれを修正した間、私は本当に理解していませんが、ここにあります。

DatabaseInitializer.cs

public class DatabaseInitializer : CreateDatabaseIfNotExists<DatabaseContext>
{
  protected override void Seed(DatabaseContext context)
  {
    // Seed code here
  }
}

DatabaseContext.cs

public class DatabaseContext : DbContext
{
  public DatabaseContext() : base("MyDatabase") { }

  protected override void OnModelCreating(DbModelBuilder mb)
  {
    // Code here
  }

  public DbSet<Entity> Entities { get; set; }
  // Other DbSets
}

Global.asax.cs-Application_Start()

protected void Application_Start()
{
  Database.SetInitializer(new DatabaseInitializer());
  AreaRegistration.RegisterAllAreas();
  RegisterGlobalFilters(GlobalFilters.Filters);
  RegisterRoutes(RouteTable.Routes);
}
62
Alec

これは私のDbContextクラスがすべてどのように見えるかであり、それらはうまくシードします:

public class MyDbContext : DbContext
{
    public DbSet<MyClass> MyClasses { get; set; }

    protected override void OnModelCreating (DbModelBuilder modelBuilder)
    {
        base.OnModelCreating (modelBuilder);
        modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention> ();

        // Add any configuration or mapping stuff here
    }

    public void Seed (MyDbContext Context)
    {
        #if DEBUG
        // Create my debug (testing) objects here
        var TestMyClass = new MyClass () { ... };
        Context.MyClasses.Add (TestMyClass);
        #endif

        // Normal seeding goes here

        Context.SaveChanges ();
    }

    public class DropCreateIfChangeInitializer : DropCreateDatabaseIfModelChanges<MyDbContext>
    {
        protected override void Seed (MyDbContext context)
        {
            context.Seed (context);

            base.Seed (context);
        }
    }

    public class CreateInitializer : CreateDatabaseIfNotExists<MyDbContext>
    {
        protected override void Seed (MyDbContext context)
        {
            context.Seed (context);

            base.Seed (context);
        }
    }

    static MyDbContext ()
    {
        #if DEBUG
        Database.SetInitializer<MyDbContext> (new DropCreateIfChangeInitializer ());
        #else
        Database.SetInitializer<MyDbContext> (new CreateInitializer ());
        #endif
    }
}

私はこのパターンを数回使用しましたが、非常にうまく機能しました。

37
Jim D'Angelo

Seedメソッドは、Database.SetInitializerApplication_Startへの適切な呼び出しでも呼び出されませんでした。その理由は本当に単純でした。 実際に使用するデータベースコンテキストのコードがあります。

10
user1068352

これは私の悲しい小さな物語です。

まず、学んだ教訓:

  1. コンテキストが使用されるまで、シードメソッドは呼び出されません。
  2. Global.asax.csは、デバッガーが接続される前に実行される最初のbcでブレークポイントにヒットしません。 Global.asax.csでブレークポイントをヒットするには、空白をWeb.configに追加してページをヒットできます。その後、ヒットします。
  3. データベースへのVS接続がある場合、シードは行われません。アプリはエラーをスローします。

それで、悲しみを避けるために:

  • VS接続を切断します。
  • 基本クラスDropCreateDatabaseAlwaysを一度に切り替えます。
  • コンテキストを使用するページをヒットします。

今、悲しみ:

  1. Global.asax.csファイルにカスタムのInitializerクラスがありました。イニシャライザにブレークポイントがありましたSeedメソッド;アプリケーションを起動しましたが、メソッドがヒットしませんでした。:(
  2. Application_StartのDatabase.SetInitializer呼び出しでブレークポイントを指定します。それは決して当たりませんでした。 :(
  3. Dbスキーマの変更がないことに気付いたので、DropCreateDatabaseIfModelChangesをDropCreateDatabaseAlwaysに変更しました。それでも、何も。 :(
  4. コンテキストを使用するページにようやく行きましたが、うまくいきました。 :/
9
Davious

update-databaseを呼び出して、Configurationクラス内でシードメソッドを手動で実行できます。これには、enable-migrationsもオンにする必要があります。

PM> update-database
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
No pending code-based migrations.
Running Seed method.

internal sealed class Configuration : DbMigrationsConfiguration<ProjectManager.Data.Database.ProjectDb>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
    }

    protected override void Seed(ProjectManager.Data.Database.ProjectDb context)
    {
        context.Status.AddOrUpdate(
            new Status() { Id = 1, Text = "New" },
            new Status() { Id = 2, Text = "Working" },
            new Status() { Id = 3, Text = "Completed" },
            new Status() { Id = 4, Text = "Skipped" }
        );
    }
}
3
Despertar

Global.asaxファイルの次の変更は、私にとってはうまくいきました。

古いコード:

    protected void Application_Start()
    {
        Database.SetInitializer<mycontextclassname>(new DropCreateDatabaseAlways<mycontextclassname>());             
       ...
    }

新しいコード:

    protected void Application_Start()
    {
        Database.SetInitializer<mycontextclassname>(new DropCreateDatabaseAlways<mycontextclassname>()); 
        Database.SetInitializer(new Initializer()); 
        ...
    }
2
Steven Burton

私もSeed()を呼び出すのに苦労しました。そして、私は上記のすべての有用な提案に感謝し、DropCreateDatabaseAlwaysを使用して運がありました...常にではありません!!

直近では、リポジトリのコンストラクターに次のコード行を追加して効果を上げました。

    public CatalogRepository()
    {
        _formCatalog.FormDescriptors.GetType();

    }

Seed()の呼び出しをトリガーするだけで十分でした。この答えより上ですべて試してみてもまだ運がない場合は、試してみてください。幸運なことに、これは本当に時間のかかる経験でした。

1
Joe

私は同じ問題を抱えていて、両方を変更した後Global.asaxファイルとIntializerファイルが機能しました。データのシードにまだ問題を抱えている人にとってはうまくいくと思います。

Global.asaxの新しいコード:

    protected void Application_Start()
    {
        Database.SetInitializer<mycontextclassname>(new DropCreateDatabaseAlways<mycontextclassname>()); 
        Database.SetInitializer(new Initializer()); 
        ...
    }

intializerファイルのコード:

public class Initializer : System.Data.Entity.DropCreateDatabaseAlways<Context>
0
mudassir sheikh

この問題に出会ったばかりです。 Web.configファイルから「connectionstrings」セクションを削除しましたが、現在、アプリは実行を開始しました-connectionstringsセクションなし!セクションを追加し直しても、データベースは再びシードされません。これは適切な解決策ではありませんが、問題を潜在的に解決できるものにここにデータポイントを追加しています。

幸いなことに、それは私がとにかくすぐに破棄する小さな「使い捨て」アプリです...

0
Evgeny

コンテキスト変数を複数回宣言していないことを慎重に確認してください。シード後に再度宣言すると、シードは上書きされます。

0
KSHMR

この回答が間違っていることに注意して更新されました!私のDBがシードされない理由は謎のままです(ただし、@ JaredReisingerで指摘されているように、デフォルトのベースコンストラクター呼び出しがないわけではありません)

私はこの質問が少し古いことを感謝していますが、他の誰かがそうするかもしれないので、私はここに行きました。ここに私のタッペンスの価値がある:

データベースを削除し、DropDatabaseInitialiserを使用して再度開始しても、DBは正常に作成されましたが、シードされませんでした。

上記のコードを読んだ後、私は私のコンテキストコンストラクタがこれであることに気づきました

public MyApp_Context()
{
    // some code
}

一方、上記の例は私の設定では次のようになります

public MyApp_Context() : base("name=MyApp_Context")
{
    // some code
}

うん、私はベースオブジェクトのコンストラクタを呼び出していませんでした!この場合、シードを除くすべてが機能するとは思っていませんでしたが、それは(繰り返し可能な)ケースのようです。

注:実際には、ベースコンストラクターの呼び出しでコンテキスト名を指定する必要はありません。上記のソリューションの形式をコピーしていたため、最初はそのようにしか書きませんでした。したがって、私のコードはこれであり、シードは最初のデータベース作成で機能します。

public MyApp_Context() : base()
{
    // some code
}
0
Jon

この例のシードイベントは、DropCreateDatabaseIfModelChangesを使用して一度だけ起動されるため、これをDropCreateDatabaseAlwaysに変更でき、毎回シードイベントを起動する必要があります。

編集

これは私のDataContextです

public WebContext()
{   
    DbDatabase.SetInitializer(new DropCreateDatabaseIfModelChanges<WebContext>());
}
0
Richard Forrest

これは、私がCode First Featuresを発見しているときに起こったものです。この状況は、初期化戦略なしで最初にCode Firstを使用してデータベースを生成したときによく発生します。

後でDropCreateDatabaseIfModelChangesベースの戦略を実装することで、モデルを変更せずにそうすることにした場合、データベースの生成と戦略のみが実行されるため、Seedメソッドは呼び出されません。次回モデルを変更するときに適用されます。

これがあなたに起こったら、この仮説をテストするためにモデルを少し修正してみてください、そして私は間違いなく、あなたのデータベースは移入されるでしょう;)

常にデータベースを生成する戦略を使用することを除いて、まだ解決策はありませんが、このクラスは本番環境で使用される予定なので、DbContextに初期化戦略を置くという事実には本当に不安です。ただし、初期化戦略は、流な開発環境に主に使用されるようです。

0
Bruno