Entity Frameworkには後方互換性を確保していないという,やや不名誉な評判がある。しかしEntity Frameworkコアで実施されている全面的な刷新に比べれば,それは大した問題ではない。今回の記事では主要な機能変更と,その影響のいくつかを確認する。
延期された機能と非推奨機能
まず最初に,EF Core 1.0ではサポートされないEF 6の機能と, EF Core 1.1のロードマップに記載のない機能を確認しよう。
遅延ローディング
遅延ローディング(Lazy Loading)はEntity FrameworkやORM一般において,いつも論争の的になる問題である。EFでは元々,遅延ローディングをサポートする予定はなかった。誤った使い方によってパフォーマンス低下を生じることが少なくないためだ。
その一方で,パフォーマンスが重要でないラピッドプロトタイピングやユーティリティアプリケーションでは,遅延ローディングは非常に便利な機能である。そのため,第2のメジャーバージョンであるEF 4で追加されることになった。(注: .NET Frameworkのバージョン番号に合わせるため,EFではバージョン2と3をスキップしている。)
歓声と驚きの声を受けながら,EF Coreは遅延ローディングのサポートなしで公開された。現時点でアドバイスできるのは,”自分自身で遅延ローディングが可能になる”EF Core 1.1まで待つ,という方法だ。GitHubやその他のさまざまな議論で見る限り,EFが遅延ローディングを直接サポートするかどうかは明確ではない。
GROUP BY変換
これはよく分からない。LINQ to SQLで10年前からサポートされているにも関わらず,EF CoreのロードマップにはGROUP BYのサポートが掲載されていないのだ。つまりグループ操作を含むクエリを行なうと,EF Coreによるクエリ生成ではGROUP BYが省略されることになる。
当然の結果として,集約に先立ってミドル層からすべての対象データを移動させなければならず,必要なネットワーク帯域が大幅に増加する。増加したデータのデシリアライズにはコストが伴う上に,実際にグループ操作を行なう上では,C#の方がデータベースよりも効率面で劣る可能性が高い。(データベースには,テーブルサイズやデータ分布などのテーブル統計を使ってアルゴリズムを最適化できるアドバンテージがあるからだ。)
ストアドプロシージャ
Microsoftによるもうひとつの驚くべき行動は,ストアドプロシージャをサポートしないという決定だ。raw SQLを使えば,技術的にはまだアクセス可能だが,この方法には多くの制限事項がある。
- SQLクエリが使用できるのは,自身のモデルに含まれるエンティティタイプを返す場合のみに限定される。[この機能は.NET Core 1.1で予定されている]
- SQLクエリは,そのエンティティタイプの全プロパティにデータを返さなくてはならない。
- リザルトセットのカラム名は,プロパティがマップされたカラム名と一致していなくてはならない。rawSQLクエリでプロパティ/カラムマッピングが無視されるEF6.xとは異なり,リザルトセットのカラム名とプロパティ名の一致が必要な点には注意が必要だ。
- SQLクエリに関連データを含めることはできない。ただし多くの場合は,関連データを返す(つまり関連データを含む)includeオペレータを使うことで,そのクエリ上に構成することができる。
WhereあるいはOrderByコールをテーブル値関数クエリに追加するなど,raw SQLをLINQ式と混在させることが可能な場合もある。
空間データ型
空間データ(Spatial Data)型は興味深いケースだ。純粋なADO.NETを使用する場合,COMライブラリ(Microsoft.SqlServer.Types)のラッパとしてSQL Serverに含まれている空間データ型を使用する必要がある。COMは特にライブラリ配布や登録が必要な点において.NETと整合性がよくないため,Entity Frameworkではそれに対応した空間データ型(System.Data.Spatial)を独自に用意している。 どちらのAPIもOGC(Open Geospatial Consortium)仕様に基づくものであるため,基本的な機能面での差はほとんどない。
ここまでは主として,SQL Serverについて話を進めてきた。他のデータベースは異なる空間タイプを実装しているので,Microsofrtがこの問題の解決に時間を要しているのは理解できる。
シードデータ
データベースのマイグレーションはEF Coreによってサポートされているが,シードデータをルックアップテーブルに投入する機能が不足している。
シンプルなコマンドインターセプト
コマンドのインターセプトは,Entity FrameworkのSQLジェネレータの制限を回避する手段として広く利用されている。例えばEFでフルテキスト検索インデックスを使用したい場合には,IDbCommandInterceptorを実装した上で,ReaderExecutingおよびScalarExecutingメソッドをオーバーライドする必要がある。
このテクニックはかなり厄介である上,SQL EFの生成する内容に関する正確な知識に強く依存しているが,これがなければ,データベースの先進的な機能の多くがアクセス不能になる。
ツーリング
以前の記事で述べたように,LINQ to SQLとEntity Frameworkで当初提供されていたグラフィカルなモデリングツールは,EF Coreでは提供されない。
さらに現時点では,データベースからモデルを更新可能にするという計画もない。データベースからのモデル生成は,少なくとも近い将来に関しては,ワンタイムイベントのままということになる。
EF Core 1.1の特徴
EF Core 1.1は来年の第1四半期にリリースが予定されている。バグフィックスや以下の機能に加えて,機能の安定化も行われる見通しだ。
SQL変換の改善
厄介なことに,この章には詳細が書かれていない。“正常に実行できるクエリが多くなり,より多くのロジックが(インメモリではなく)データベースで実行されるようになった”,とあるのみなのだ。別の場所では,EF 6が“単純”,“中程度”,“複雑”なクエリをサポートする,と書かれている。中程度のクエリはEF Core内で“安定”しており,複雑なクエリのサポートは開発中である。
カバーされるシナリオに関するヒントはいくつかあるが,生成されたSQLに特別な注意を払い,データベース呼び出しをプロファイルし,EFの動作が適切なものであることを確認する必要がある。
同じく,ナビゲーションプロパティを使用したクエリについても,まだ開発途上であると考えられる。
非モデル型のクエリ
上述のようにEF Core 1.1では,モデルに含まれない型を具象化できるようになるはずだ。
DbSet.Find
EF 5のこの便利なメソッドは,明示的に名前を付けなくても,プライマリキーを使ってレコードをロードすることができる。コンテキストのキャッシュにフックするため,不必要なデータ呼び出しが回避されている。コンテキストにアタッチされてはいるが,データベースには保存されていないレコードを探すことも可能だ(ただし識別/自動採番カラムを使用していないという条件がある)。
EntityEntryおよびObjectStateEntry API
EntityEntryおよびObjectStateEntryの追加機能として,Reload,GetModifiedProperties,GetDatabaseValuesなども予定されている。
明示的ローディング
“イーガーローディング(Eager Loading)”と混同してはならない。明示的ローディング(Explicit Loading)は子のコレクションを,エンティティがマテリアリズされた後にロードできるようにするものだ。別ステップを備えた遅延ローディングと考えればよい。
コネクション回復
将来有望なこの機能は,コネクションの問題が原因で失敗したトランザクションを再試行するものだ。“トランジェントな障害の多いSQL Azureに接続する場合には特に便利です。”
EF Core vNext機能
EF Core 1.1の時間枠内での完成は難しいと思われるが,その他にも開発中の機能がある。
- Complex/value型。プライマリキーを持たず,特定のエンティティ型のプロパティセットを表すために使用される。
- string => xmlのようなシンプルな型変換。
- 既存データベースからモデルをリバースエンジニアリングするためのVisual Studioウィザード。
この記事を評価
- 編集者評
- 編集長アクション