15

Entity Framework 6 に移行した後、ビルド サーバーで単体テストを実行するとエラーが発生します。

DropCreateDatabaseIfModelChangesイニシャライザを使用しています。すべてに変更するとMigrateDatabaseToLatestVersion機能しますが、以前の初期化子に固執したいと思います。

私が得ているエラーは次のとおりです。

System.InvalidOperationException: System.InvalidOperationException: データベースが作成されてから、'AppContext' コンテキストをサポートするモデルが変更されました。Code First Migrations を使用してデータベースを更新することを検討してください ( http://go.microsoft.com/fwlink/?LinkId=238269 )。

どちらが正しいですか、変更されましたが、DropCreateDatabaseIfModelChanges初期化子を使用して再作成する必要があります。何か案は?

EF は App.config で構成されます。関連する部分は次のとおりです。

<connectionStrings>
    <add name="AppContext" connectionString="Data Source=(localdb)\v11.0;Initial Catalog=my.app.unittest;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>
<entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
        <parameters>
            <parameter value="v11.0" />
        </parameters>
    </defaultConnectionFactory>
    <contexts>
        <context type="my.app.core.Data.AppContext, my.app.core">
            <databaseInitializer type="System.Data.Entity.DropCreateDatabaseIfModelChanges`1[[my.app.core.Data.AppContext, my.app.core]], EntityFramework" />
        </context>
    </contexts>
    <providers>
        <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
</entityFramework>
4

5 に答える 5

19

EF 6.0 では新しいルールが導入されているようです。

「DbContext が初期化子を使用しており、移行が構成されている場合は、モデルの構築時に例外をスローします」。

EF 6 RC までは、これは強制されていませんでした。厄介な部分は、「移行が構成されている」が DbMigrationsConfiguration の実装によって定義されていることです。テストで移行をプログラムで無効にする方法はないようです-実装した場合

Sebastian Piu と非常によく似た方法でこの問題を回避しました。テストから Configuration クラスを削除する必要がありましたが、メイン プロジェクトに Migrations を使用しているため、単に削除することはできませんでした。ああ!

これは以前の私のコードでした:

public class MyDbContext : DbDContext, IMyDbContext
{
  public IDbSet<Users> Users {get; set;}
  public IDbSet<Widgets> Widgets {get; set;}
}

// Migrations are considered configured for MyDbContext because this class implementation exists.
internal sealed class Configuration : DbMigrationsConfiguration<MyDbContext>
{
  public Configuration()
  {
    AutomaticMigrationsEnabled = false;
  }
}

// Declaring (and elsewhere registering) this DB initializer of type MyDbContext - but a DbMigrationsConfiguration already exists for that type.
public class TestDatabaseInitializer : DropCreateDatabaseAlways<MyDbContext>
{
    protected override void Seed(MyDbContext context) { }
}

テスト コードで DbContext が初期化されているときに System.InvalidOperationException が発生しました。アプリケーションはイニシャライザを使用しないため、以前と同様にアプリケーションの実行に問題はありませんでした。これは私のテストを破っただけです。

解決策 (EF にないものに対する回避策のように感じます) は、Initializer と DbMigrationsConfiguration をセグメント化して、ランタイム環境で 1 つだけが表示されるようにすることです。テストで Initializer を使用し、アプリケーションで DbMigrationsConfiguration を使用したいと考えています。これは、DbContext にインターフェイスがあればもっときれいに行うことができますが、残念ながら IObjectContextAdapter しか実装していません。

まず、DbContext を抽象化しました。

public abstract class MyDbContextBase : DbContext, IMyDbContext
{
      public IDbSet<Users> Users {get; set;}
      public IDbSet<Widgets> Widgets {get; set;}
}

次に、2 つのクラスを派生させました。

public class MyDbContext : MyDbContextBase
{
  public MyDbContext(string connectionStringOrName, IDatabaseInitializer<MyDbContext> dbInitializer) 
    : base(connectionStringOrName)
  {
  }
}

public class MyTestDbContext : MyDbContextBase
{
  public MyTestDbContext(string connectionStringOrName, IDatabaseInitializer<MyDbContext> dbInitializer) 
    : base(connectionStringOrName)
  {
    Database.SetInitializer(dbInitializer);
  }
}

MyDbContext と MyTestDbContext はどちらも IMyDbContexts であるため、既存の依存性注入の設定は変更を必要とせずに機能するはずです。Spring.NET のみをテストしました。

私の DbMigrationsConfiguration は、テストで使用されていない派生型を実装しています。

internal sealed class Configuration : DbMigrationsConfiguration<MyDbContext>
{
  public Configuration()
  {
    AutomaticMigrationsEnabled = false;
  }
}

最後に、イニシャライザの型は、派生したテスト クラスの型に移動されました。

public class TestDatabaseInitializer : DropCreateDatabaseAlways<MyTestDbContext>
{
    protected override void Seed(MyTestDbContext context) { }
}

テストに合格し、アプリケーション (および移行) が以前と同じように機能していることを確認できます。

于 2013-10-20T20:54:32.267 に答える
5

EF6 にアップグレードした直後に同じ問題が見つかりました。Stefan のコメントを読んで、彼が説明したのと同じ症状が発生した後 (テストはメイン プロジェクトから構成クラスを読み込んでいました)

私の場合の解決策/回避策は

  • class TestContext: MyDataContextTests プロジェクトで新規作成
  • イニシャライザを からDropCreateDatabaseAlways<MyDataContext>に変更しますDropCreateDatabaseAlways<TestContext>
  • テストコンテキストを使用するために実際のコンテキストを作成した場所を更新/一般化する

私のテストのほとんどは PersistenceTest クラスから拡張されているだけなので、これを行うことができました。そのため、大きなカタログがある場合、これを変更するのは面倒かもしれないことを理解しています。他のソリューションを楽しみにしています

于 2013-10-20T15:02:00.957 に答える
3

移行が有効になっており、DropCreateDatabaseIfModelChanges 初期化子を使用しているため、これはスローされています。Entityframework は、移行でのこの初期化子の使用をサポートしていません。次の 2 つのオプションがあります。

  • イニシャライザを無効にする

また

  • 移行構成を削除して移行を無効にする
于 2013-10-18T16:08:51.127 に答える
1

私にとってうまくいくのは、を使用して移行を除外することdefineです。方法は次のとおりです。

  • Testを定義する と呼ばれる新しい構成を作成します。TEST
  • TESTテストでは、が定義されていない場合にエラーをスローします。
  • TESTが定義されている場合は移行を除外します。
#if !TEST
internal sealed class Configuration : DbMigrationsConfiguration<Context>
{
    //...
}
#endif

すべての移行を除外する必要があるかもしれませんが、これも完全に満足できるものではありません (ただし、まだ移行がないため、試していません)。

于 2014-02-12T09:12:58.587 に答える