QA@IT

Entity Framework Code Firstで新規のデータベースを作成する場合、空のデータベースが存在してはいけないのでしょうか?

9425 PV

ASP.NET MVCでSQL CE + EFコードファーストを使用しようとしています。

  • ModelクラスとDbContextを定義し
  • ConnectionStringを設定
  • SQL CEのsdfファイルをApp_Dataに追加し
  • SaveChanges()すると (箇条書きにならないな...) 以下のような例外が飛びます。

System.Data.Entity.Infrastructure.DbUpdateException がキャッチされました
HResult=-2146233087
Message=エントリを更新中にエラーが発生しました。詳細については、内部例外を参照してください。
Source=EntityFramework
StackTrace:
場所 System.Data.Entity.Internal.InternalContext.SaveChanges()
...
InnerException: System.Data.UpdateException
HResult=-2146233087
Message=エントリを更新中にエラーが発生しました。詳細については、内部例外を参照してください。
Source=System.Data.Entity
StackTrace:
場所 System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter)
...
InnerException: System.Data.SqlServerCe.SqlCeException
HResult=-2147467259
Message=指定されたテーブルは存在しません。 [ Clients ]
Source=SQL Server Compact ADO.NET Data Provider
ErrorCode=-2147467259
NativeError=0
StackTrace:
場所 System.Data.SqlServerCe.SqlCeCommand.ProcessResults(Int32 hr)
...
InnerException:
(引用の中でインデントしたいな...)

色々と試行錯誤してみたのですが、結局空のsdfファイルが存在するとテーブルを作成しようとせずこの例外が発生し、sdfファイルを削除し、sdfの生成をEFにやらせると問題なく動くようです。
DbContextにテーブル作成のためのメソッドも見当たりませんし、この動作は仕様と考えてよいのでしょうか?

現象自体は回避できているのですが、どうも腑に落ちないので質問してみています。
Code Firstは何かとblogエントリーに飛ばされるので、正しい仕様というのがよくわからず戸惑い気味です。この動作に関する仕様などのリファレンス先などわかると幸いです。

回答

まず仕様かどうかですが、その動作(Exception)は仕様です。

テーブルを追加するということはデータベースのスキーマ変更と言うことになりますが、その際、なんの操作もしなければ、たとえ空のデータベースであったとしてもエラーになります。(これはSQL CEだけで無く、SQL Serverの場合も同じはずです。既存データベースに対して、スキーマ変更を無理すればたいていの場合データ破壊になってしまいますから。)

ですので、DbModelに変更があった場合にはデータベースを作り直すよう、以下のようにDataBase.SetInitializerメソッドを、実際にDbModelのインスタンスを作る前に動作するように設定します。

Database.SetInitializer(new DropCreateDatabaseIfModelChanges());

using(var hoge = new HogeContext()) {
...
}

当然のことながら、本運用に入るシステムがこのままで良いかはちょっと考えてくださいw

編集 履歴 (0)

なるほど、スキーマの変更を行う以上テーブルを格納しているデータベースそのものを作り直す必要がある、SQL CEの場合はデータベースとはsdfファイルそのもの、ということでよいでしょうか。
SQL CEのsdfファイルがある種のコンテナ的な存在でその中に複数のデータベースが作られるような印象を持っていたので、そのあたりがかけ違いの原因のようです。
もやもやがかなりすっきりしました。ありがとうございます!

(回答への返信をノートに書こうとしたら200字越えてしまって書けないとか、どうするのが想定されている使い方なのだろう...)

編集 履歴 (0)

ああ、あと、RailsのマイグレーションのようなことをEFに期待されているならだめです。現状のEFではRailsのマイグレーション相当の機能は無いです。

編集 履歴 (0)
ウォッチ

この質問への回答やコメントをメールでお知らせします。