web-dev-qa-db-ja.com

Entity Framework 4.1データベースが作成されてから、DBを作成した直後に、コンテキストをサポートするモデルが変更されました

さまざまなオブジェクトをデータベースに永続化するためにEntityFramework 4.1を使用するプロジェクトに取り組んでいます(コードファースト)。

VisualStudioでローカルのSQLExpress DBを使用してテストしていますが、Jenkinsサーバーはコミットされたコードをテストサーバーにデプロイします。これが発生した場合、テストDBサーバーを指すようにローカル接続文字列を一時的に変更し、単体テストを実行して、最新のエンティティなどと一致するようにテストデータベースを再作成します。

最近、テストサーバーで次のエラーが発生していることに気付きました。

'EntityFrameworkUnitOfWork'コンテキストをサポートするモデルは、データベースの作成後に変更されました。データベースを手動で削除/更新するか、IDatabaseInitializerインスタンスを使用してDatabase.SetInitializerを呼び出します。たとえば、DropCreateDatabaseIfModelChangesストラテジーは自動的に削除して再作成します。データベース、およびオプションで新しいデータをシードします。

これは通常、コードが変更されたことを示しており、データベースを再作成するために単体テストを実行する必要があります。私がそれをしたことを除いて!展開プロセスに問題はないと思います。テストサーバー上のDLLは、ローカル環境と同じバージョンのようです。データベースの作成後にモデルが変更されたことについて、このエラーを引き起こす可能性のある他の設定または環境要因はありますか?

私はここで新しいです-助けてくれてありがとう!

24
DaveBeta

表示されるエラーは、EdmMetadataテーブルに格納されているモデルハッシュが、アプリケーションのモデルから計算されたモデルハッシュとは異なることを意味します。別のアプリケーション(開発アプリケーション)からデータベース作成を実行しているため、これら2つが異なる可能性があります。ここでの簡単なアドバイスは次のとおりです。データベースの作成に別のアプリケーションを使用せず、代わりにメインアプリケーションにデータベースを作成させます(自動的に、またはたとえば管理インターフェイスを使用して)。

別のオプションとして、これらのチェックの原因となる規則を削除することで、このチェックを完全にオフにできるはずです。

modelBuilder.Conventions.Remove<IncludeMetadataConvention>();

モデルハッシュの計算は、アプリケーションの現在のエンティティ(単純な変更は異なるモデルハッシュになります)およびデータベースサーバーのバージョン/マニフェストに依存します。たとえば、SQL Server 2005および2008に展開されたモデルは、異なるモデルハッシュを持ちます(ExpressとFull、または2008と2008 R2は、異なるモデルハッシュになるべきではありません)。

25
Ladislav Mrnka

これは、異なるプラットフォーム間でのリフレクションの順序の違いが原因で発生する可能性があります。確認するには、EdmxWriter APIを使用して、両方の環境のEDMXを比較できます。いずれかのテーブルの列の順序が異なる場合、これが問題です。

回避策として、ローカルボックスではなくテストサーバーから更新されるように、テストデータベースの更新方法を変更できます。

この問題は次のリリースで修正する予定です。

9
Andrew Peters

コードファーストアプローチでは、SSDLはコードの実行中に生成されます。生成されたSSDLに含まれる情報の1つは、DbConnectionで使用されるプロバイダーの名前です。あなたが言ったように、あなたは異なるデータベースエンジンに接続しているので、2つの異なるプロバイダーを使用する必要があります。これにより、ハッシュ関数の出力が完全に変更されます。

以下のコードは、EntityFrameworkアセンブリから抽出されました。

using (XmlWriter writer = XmlWriter.Create(output, settings))
{
    new SsdlSerializer().Serialize(database, providerInfo.ProviderInvariantName, providerInfo.ProviderManifestToken, writer);
}
6
Diego Frata

これは役立つかもしれません、そしてスコットGブログへのリンクはあなたの問題の解決策になるでしょうこの質問をチェックしてください リンク

編集1:これは スコットGブログへのリンク

編集2:統合サーバーで最初にデータベースを使用する場合は this も確認できます

編集3:これは より詳細な回答 スコットGのもののようです

3
radu florescu

アプリケーションを実行している2つのサーバーが異なるオペレーティングシステム(またはサービスパック)を実行していますか?使用されているSHA256CryptoServiceがPlatformNotSupportedExceptionをスローして、別のメソッドにフォールバックする可能性があるようです。

http://msdn.Microsoft.com/en-us/library/system.security.cryptography.sha256cryptoserviceprovider.sha256cryptoserviceprovider.aspx

// System.Data.Entity.Internal.CodeFirstCachedMetadataWorkspace
private static SHA256 GetSha256HashAlgorithm()
{
  SHA256 result;
  try
  {
    result = new SHA256CryptoServiceProvider();
  }
  catch (PlatformNotSupportedException)
  {
    result = new SHA256Managed();
  }
  return result;
}

リフレクションを使用して、各サーバーで次の2つの(内部/プライベート)メソッドを呼び出すことで、これをテストできる場合があります。

MetaDataWorkspace.ToMetadataWorkspace(DbDatabaseMapping, Action<string>)
CodeFirstCachedMetadataWorkspace.ComputeSha256Hash(string xml);
3
Betty

Entity Frameworkコードは、最初にEdmMetadataというテーブルを作成します。現在のモデルのハッシュを保持します。アプリケーションを実行すると、EFは、使用されているモデルがdb 'が認識しているモデルと同じであるかどうかを確認します。

データベースの移行を実行する場合は、まだアルファ版ですが、 EFコードの最初の移行 を使用することをお勧めします。

移行を使用したくない場合は、次のいずれかを実行できます。

スキーマの変更を手動で処理します。つまり、EdmMetadataテーブルのコンテンツをすべての変更とともにテストサーバーに移動します。

または

db初期化子をDropCreateDatabaseIfModelChangesに設定します(または、db初期化子から派生したもので、Seed()メソッドを使用して初期データを書き込みます)。イニシャライザーを設定するには、アプリケーションの起動時にDatabase.SetInitializer()を呼び出すか、appSettingsを使用します

<add key="DatabaseInitializerForType Fully.Qualified.Name.Of.Your.DbContext," value="Fully.Qualified.Name.Of.The.Initializer" />
2
Chris

誤って.mdfファイルの名前を変更しただけで、このエラーが発生しました。だからこれも探してください。

0
Roman Pawlig