マイクロソフト系技術情報 Wiki」は、「Open棟梁Project」,「OSSコンソーシアム .NET開発基盤部会」によって運営されています。

目次

概要

Entity Frameworkを利用する上での懸念をまとめてみた。

外部スキーマ云々

JOINのサポート

JOINの使用

JOINを使用しない内部結合

集計処理のサポート

性能云々

全体的に、

  • contextへのアクセス
  • 呼び出すLINQメソッド

から

  • どういうSQLが実行されるのか?
  • 内部動作はどのようになっているのか?

などがブラックボックス化されているため、
Entity Framework自体の仕様に精通していないと、

ハイパフォーマンスな実装をすることができない。

という問題がある。

検索SQLが検索キーや射影の列名を指定しない

foreachでデータアクセスした場合など、
検索SQLが検索キーや射影の列名を指定しないので性能的に問題になる。

Iterator的にDBアクセスしてしまう。

以下の様な手段により、処理対象のEntityをメモリに起こしてしまう。

ToArray?()メソッド

この場合、ToArray?()メソッドを使って、はじめに結果を確定させる。

var YYYYYs = context.YYYYYs.ToArray();

Load()メソッド

この場合、Load()メソッドを使って、DbContext?内にデータをキャッシュさせる。

context.YYYYYs.Load();

この後、context.YYYYYsにアクセスしてもSQLは実行されない。

大量データ処理

ライブラリがいくつかある。(非 MS 製、NuGet からインストール可能)

LINQ to Object vs LINQ to Entities

処理される場所が異なる

となる。

  • ストレージが必要な大量データ処理になってくると、
    LINQ to Entitiesの方が高速になる可能性がある。

処理結果が異なる

処理される場所だけでなく、処理結果が異なることがある。

  • 以下は、DB側でNameでソート(OrberBy?)される。
    context.YYYYYs.OrberBy(x => x.Name).ToArray()
  • 以下はDBからロードされた後、メモリ上でNameでソート(OrberBy?)される。
    context.YYYYYs.ToArray().OrderBy(x => x.Name)

DBMSの照合順序などの関係により、
処理される場所によって、ソート(OrberBy?)順が異なるためである。

トラッキングしない

AsNoTracking?()メソッドでCollectionを取得すると、
Entity Statesのトラッキングをしなくなる。

var YYYYYs = context.YYYYYs.AsNoTracking().ToArray();

これにより、使用するメモリ量を削減できる。

コードファースト云々

  • クラス名(+s)がテーブル名にマップされる。
  • プロパティ名がカラム名にマップされる。
  • 主キーはid or クラス名 + id がデフォルト。

マイグレーション

コードファーストのデータモデルクラスの変更をもとに、
既存のデータを残したままデータベースのテーブルを変更する機能。

規約

コードファーストでは規約に基づいてEntityとDatabaseを紐付ける。

属性

属性による規約

項番属性名説明
TableEntityとTable間のマッピング
ColumnEntityのPropertyとTableのColumn間のマッピング
ComplexType?Entityの複数のProperty(Properties)とTable間のマッピング
ComplexType?の複数のProperty(Properties)は、別のTableに切り出される。
KeyEntityのPropertyを対応するTableのPrimaryKey?に設定する。
RequiredEntityのPropertyに対応するTableのColumnをNOT NULLに設定する。
MVCのModelMetadata?として検証処理に使用される。
MaxLength?EntityのPropertyに対応するTableのColumnのデータ長を設定する。
MVCのModelMetadata?として検証処理に使用される。
IndexEntityのPropertyに対応するTableのColumnを使用した非クラスタ化・インデックスを作成する。
NoMapped?EntityのPropertyをDatabaseにマップしない。

その他、DbContext?を継承したContextのコンストラクタで接続文字列を決定できる。

Fluent API

Fluent APIによる規約

ナビゲーション・プロパティ

エンティティ間の関連(アソシエーション)を表す。

  • x対一は、オブジェクト参照を使用。
  • x対多は、ICollection<T>を使用。

批判云々

  • 性能と柔軟性が重視されるエンタープライズの領域では、使い難いとの批判も多い模様。
  • ツール等のスタンドアロンのプログラム、情報系システムなどのEUCによるRAD開発などにはマッチする可能性もある。
  • また、ADO.NETは枯れた技術であるのに対し、Entity Frameworkは進化の余地がある。

信任投票

ORMの問題

気付き

Entity FrameworkをキャンセルしたASP.NET Identity
UserStoreを実装して「ORMの問題だな。」と思った点は、

プログラムの

  • インターフェイスとなっている親子階層のあるオブジェクト・モデルと、
  • ストレージとの同期処理(セーブ・ロード)のタイミングなどが、

実装者にとって「難しい。」ってトコロではないかと思う。

背景

  • 難しさの背景は、
  • 自分でUserStoreを実装していてもこの同期は難しい。
    • 同期処理の仕様を決める必要がある。
    • 同期処理の仕様を思い出し、
      処理全体との繋がりを理解する必要がある。

等と言った点だと思う。

  • UserStoreは、MemoryモードとDBMSモードを処理するので、
    Memoryモードの実装の後、DBMSモードを実装しようとしたタイミングでこの難しさに気付く。
  • オブジェクトを操作したタイミングで直ちに同期される仕様にすれば、問題はなくなるが、
    実際は、性能云々に書いたように、性能を考慮して適切なタイミングに同期する必要がある。

エンプラ領域でのミスマッチ

基幹系システムでは以下の理由でミスマッチと判断されることが多い。

インピーダンス・ミスマッチ

概念モデルに対してプログラミングを採用している。

  • 外部スキーマを使用できないため、論理データ独立性が無い。
  • 概念スキーマのデータ構造を使用してプログラミングを行う必要がある。

スキーマ構造の変更

  • DBMSのスキーマからモデル(EDM)を生成する方法を採用している場合、
    スキーマの構造が変わった場合、モデル(EDM)の作り直しが発生する。
  • 生成されたモデル(EDM)をカスタマイズしていた場合、
    作り直しにより、カスタマイズが破棄されてしまう可能性がある。
    • カスタマイズがなければ、概念スキーマ構造の変更を
      モデル(EDM)に同期し、変更に迅速に対応できるとも言える。
    • しかし、論理データ独立性が無いため、プログラムの変更は必要になる。
  • RAD開発ツールに特有の、保守性の悪さがある。

内部実装とその動作がブラックボックス

SQLが、LINQ to Entityのエンジンに生成される形であり、
また、内部実装とその動作がブラックボックスになっているため(※1)
それらが明確にならないと設計、チューニング、問題分析などが困難。

従って(特に日本の)エンタープライズ・アプリケーションでは敬遠されている。
これは、JavaのJava8でJPAでHibernateでJinqが敬遠されるのと≒。

最新の動向

エンプラ界隈でのEntity Framework離れ進んでますね。

https://www.osscons.jp/jowlrb9pr-537/

NoSQL用のEntity Frameworkが流行っていない。

  • Entity Framework、RDBよりNoSQLのほうがマッチしそう。
  • しかし、長々、NoSQL用のEntity Frameworkプロバイダがリリースされなかった。
  • 2018年にEFコアがSQLデータベースとNoSQLデータベースを統一したらしい。
  • ...しかし、まったく流行っていない感。

Tags: :.NET開発, :データアクセス, :ADO.NET, :Entity Framework, 性能?


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2020-02-05 (水) 10:36:34 (1536d)