昔書いたコードのEntityFrameworkを6.0にバージョンアップしたら、いろいろ困ったという話
昔書いたコードのEntityFrameworkを6.0にバージョンアップして、
モデルを作り直したら、ObjectContextからDbContextへ変わってしまって、対応に追われました。
コードの修正したので結果を書いておきます。
何がどう変わったのか
Entity Framework 4.1でDbContext APIが追加され、軽量なDbContextクラスが追加されました。
2011年ごろだったと思いますので、すでに3年前のことです。
ADO.NET Entity Framework 4.1 における Code First
まずEntityFrameworkのバージョンと、データベースファーストでのObjectContext/DbContextの関係を整理します。
EF4.0までは、ObjectContext
EF5では、.NET 4.5の場合DbContext、.NET 4.0の場合はObjectContext(EFのバージョンは4.4でした)
EF6では、.NET 4.0でもDbContextとなりました。
なんでこんな複雑なことになっているのかは、EF5が、.NET4.5のコアに関連したようですが、EF6でそれが解消されたようです。
Entity Framework 5 のパフォーマンスに関する考慮事項
Entity Framework 6: 上級者向けエディション
バージョンアップしてモデルを作り直したら何が起きたか?
ほとんどは問題ないのですが、一部整理された部分があるので、そこだけコードの修正が必要です。
修正はめんどうですが、整理されてわかりやすくなっていると思います。
SQLコマンドの実行
ObjectContext.ExecuteStoreCommand メソッド から
DbContext.Database.ExecuteSqlCommand メソッド へ変わりました。
何かデータベースへ作用させるものは、dbContext.Databaseへまとめたということのようです。
当然CommandTimeoutなんかも移動しています。
変更の追跡
ObjectContext.ObjectStateManager プロパティ から
DbContext.ChangeTracker プロパティ へ変わりました。
GetObjectStateEntries()とか長い名前がEntries()になり、
HasChanges()なんかもついて、スッキリ便利になってます。
データベースのオプション
ObjectContext.ContextOptions プロパティ から
DbContext.Configuration プロパティ に変わりました。
エンティティーセットとクエリ
ObjectContext.ObjectSet<TEntity>から
DbContext.DbSet<TEntity>に変わりました。
エンティティーセットをWhereしてみると結果が
ObjectQuery<T>から
IQueryable<T>に変わりました。
SQLクエリの実行が
ObjectContext.ExecuteStoreQueryから
DbSet<TEntity>.SqlQueryに変わりました。
Windows FormsのBindingSource
ここが少し面倒でした。
今まではそのままクエリ結果等をDataSourceへ渡すだけでよかったのですが、
EntityFrameworkを実行すると、System.NotSupportedExceptionが発生します。
追加情報:ストア クエリ (DbSet、DbQuery、DbSqlQuery、DbRawSqlQuery) への直接のデータ バインドはサポートされていません。
代わりに、DbSet で Load を呼び出すなどして DbSet にデータを設定し、ローカル データにバインドしてください。
WPF の場合は DbSet.Local に、WinForms の場合は DbSet.Local.ToBindingList() にバインドします。
ASP.NET WebForms の場合は、クエリで ToList() を呼び出した結果にバインドしたり、モデル バインドを使用したりできます。
詳細については、http://go.microsoft.com/fwlink/?LinkId=389592 を参照してください。
だそうです。
結局どうすればいいのかというところですが、
データ取得のみの場合には、ToList()などでList<T>にしてしまえば問題ありません。
更新するデータソースの場合は、DbSet<TEntity>.Local プロパティが追加されていますので、それをDataSourceへ渡してあげればOKです。
その際あらかじめ、DbSet<TEntity>.Load()で読み込んであげてください。
あとはそのままで大丈夫でした。
DbSet<TEntity>.SqlQueryメソッドで取得したDbSqlQuery<TEntity>はLocalがありません。
そのままDataSourceへ渡してもエラーが出ます。
この場合は、ObservableCollectionを作成し、コンストラクタでDbSqlQuery<TEntity>を渡して、
作成したObservableCollectionをDataSourceへ渡してあげればOKです。
ここでしばらく嵌りました。
よくよく思い返してみれば、データアクセスの技術ってかなりの頻度で更新されてますね。
業務システムだと結構重要なところなので、非常に便利なのはいいけれど、コードの修正は大変です。
ADO.NETのDataSetとかの時代のプログラムをEntityFrameworkで書き直す気は起きません・・・。
Microsoft ADO.NET Entity Framework Step by Step (Step by Step Developer)
- 作者: John Paul Mueller
- 出版社/メーカー: Microsoft Press
- 発売日: 2013/08/15
- メディア: Kindle版
- この商品を含むブログを見る
Programming Entity Framework: DbContext
- 作者: Julia Lerman,Rowan Miller
- 出版社/メーカー: Oreilly & Associates Inc
- 発売日: 2012/03
- メディア: ペーパーバック
- クリック: 1回
- この商品を含むブログを見る
Entity Framework 6 Recipes (Recipes Apress)
- 作者: Brian Driscoll,Nitin Gupta,Rob Vettor,Zeeshan Hirani,Larry Tenny
- 出版社/メーカー: Apress
- 発売日: 2013/10/29
- メディア: ペーパーバック
- この商品を含むブログを見る
Entity Framework 4.0 Recipes: A Problem-Solution Approach (Expert's Voice in .NET)
- 作者: Larry Tenny,Zeeshan Hirani
- 出版社/メーカー: Apress
- 発売日: 2010/05/15
- メディア: ペーパーバック
- この商品を含むブログを見る
- 作者: Dr. Holger Schwichtenberg,Manfred Steyer
- 出版社/メーカー: Microsoft Gmbh
- 発売日: 2014/05/15
- メディア: ハードカバー
- この商品を含むブログを見る