昔書いたコードの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)

Microsoft ADO.NET Entity Framework Step by Step (Step by Step Developer)

 

 

Programming Entity Framework

Programming Entity Framework

 

  

Programming Entity Framework: DbContext

Programming Entity Framework: DbContext

  • 作者: Julia Lerman,Rowan Miller
  • 出版社/メーカー: Oreilly & Associates Inc
  • 発売日: 2012/03
  • メディア: ペーパーバック
  • クリック: 1回
  • この商品を含むブログを見る
 

  

Entity Framework 6 Recipes (Recipes Apress)

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)

Entity Framework 4.0 Recipes: A Problem-Solution Approach (Expert's Voice in .NET)

 

 

Entity Framework 6

Entity Framework 6