Skip to content

MS_ADONETVsORM

nishi_74322014 edited this page Aug 18, 2026 · 2 revisions

ADO.NET vs ORM (Entity Framework, Dapper)

概要

ADO.NETEntity FrameworkDapper
その他の選択肢のどれを選ぶべきか?
トレードオフがあるので、新しい技術を使っておけばイイという訳には行かない模様。

生のデータプロバイダ系(ADO.NET)

ADO.NETデータプロバイダ

SQL を使用して、二次元表形式の論理データを自由に取得できる。

DataReader, DataSet

特徴

Bean(POCO) に ORM ではなく、論理データ独立な二次元表(DataSet、DataTable)を使用できる。

  • DataAdapterDataSet オブジェクトとデータ ソース間のブリッジとして機能する。
  • DataSet の機能が必要ない場合は、DataReader を使用したほうが性能が向上する。
  • 非接続型データアクセスを実行する場合は DataSet を使用する。
    • データをローカルにキャッシュし操作する場合。
    • サーバーで取得・更新、クライアントで編集等、
      物理境界を超えてデータを持ち回って処理を行う場合。
    • Windows フォーム コントロールと連結し、対話的に編集をする場合など。
DataSet
├DataRelationCollection
├ExtendedProperties
└DataTableCollection
 └DataTable
  ├DataColumnCollection─DataColumn─ExtendedProperties
  ├PrimaryKey
  ├Constraints
  ├ChildRelations
  ├ParentRelations
  ├ExtendedProperties
  ├DataView
  ├DataRowCollection─DataRow

Bean(POCO)変換

実装は、それ程、難しくない(AutoMapper)。

適合するシステム・アプリケーション

  • 情報系システム

    • 多種・多様なビュー(二次元表形式の論理データ)にアクセスする。
    • 参照先のテーブルや取得するカラムを動的に変更するようなシステム。
  • 基幹系システム

    • 複雑なデータアクセスに対応する柔軟性と、
      大量データの処理に対応するパフォーマンスを両立させる必要があるシステム。
    • 参照したビュー(二次元表形式の論理データ)を元に更新処理を行なうシステム。

移行メモ(誤字): 元ページの「複雑なデータクセス」は「データクセス」の誤記。

DataAdapter, TableAdapter

DataAdapter / TableAdapter

ORM 的なソリューションだが、
今となっては、中途半端で、あまり利用されていない。

特徴

適合するシステム・アプリケーション

JOIN などもサポートしているもよう(下記参照)なので、
頑張れば、情報系システム、基幹系システムへの応用も可能と思われる。

移行メモ(誤字): 元ページの「JION」は「JOIN」、
「中途半場」は「中途半端」の誤記。

補足(最新化): 型付き DataSet / TableAdapter
.NET Core 以降のデザイナ サポートが無く、新規開発では使われない。
DataSet / DataTable 自体は .NET でも利用可能だが、
既存資産の保守用と考えるのが妥当である。

Open棟梁の動的パラメタライズド・クエリ

動的パラメタライズド・クエリ(OTR_DynamicParameterizedQuery.md

特徴

  • ADO.NETのラッパーライブラリ。
  • ADO.NETをラップし、動的 SQL 編集機能を同梱。

適合するシステム・アプリケーション

  • SQL 編集処理が複雑になるエンプラのドメインで使える。
    • SQL 定義をパラメタセットによって編集したい(S2Dao や iBATIS のように)。
    • メソッド(= LINQ のメソッド ベースのクエリ構文
      (メソッドチェーンやラムダ式))でクエリ編集という方式は、
      エンプラのドメインに必要とされる柔軟性が足りない。

ORM系

  • 基本的に SQL を使用せず、概念スキーマに準拠したオブジェクトにデータをストアする。
  • プログラム側のデータの持たせ方が「2 次元表」 vs Bean(POCO) と、根本的に異なる。

Entity Framework

Entity Frameworkは高機能で複雑なため、
ORM 自体の問題と、切り分けが難しい別の問題を持っている。

特徴

以下のような、3 つの開発スタイル(Entity Framework)がある。

  • モデルファースト

  • DB ファースト

    • DB 設計者(DA、DBA)の設計した DB を使用する。
    • 基幹系システムやビジネス・アプリケーションではコチラを使用する事が多いと思われる。
  • コードファースト

    • Entity の設計が DB スキーマに反映される。既存 DB にも適用可能。
    • 以下の様なシステム・アプリケーションではコチラを使用する事があると思われる。
      • クライアント・アプリケーション
      • プロトタイプ・モックアップのデータアクセス部の開発
      • SQL を駆使しない、データアクセスが比較的簡単なシステム・アプリケーション

補足(最新化:EF Core では実質コードファースト): EF Core には
モデルファースト(EDMX / デザイナ)が存在しない
現在の選択肢は、

  • Code First: C# のエンティティ クラスから
    マイグレーション(dotnet ef migrations add)で DB を生成
  • Database First 相当: 既存 DB から
    リバース エンジニアリング(dotnet ef dbcontext scaffold)で
    エンティティと DbContext を生成

の 2 つで、いずれも成果物は C# コードになる。
「DB 設計者が設計した DB を使う」場合は
scaffold してから手で調整する運用が一般的である。

適合するシステム・アプリケーション

  • データをオブジェクトとして保持しセーブ・ロードを繰り返すようなシステム
    (オンライン・ゲームなど)。
  • 単純なユーザ・ストアにアクセスして、ユーザ・データを更新するようなシステム。
  • 1 ページ、1 テーブル(ビュー)& 1 トランザクション的な、割りきった作りのシステム。
  • 例えば、クライアント・アプリケーションや、
    前述のシステム・アプリケーションに合致しないサービスなど。

参考

以下が参考になる。

Dapper

Dapperは単純な分、ORM の良さや悪さを分析し易い。

特徴

  • 厳密に言えば、ORM ではなく、Micro-ORM(DataMapper とか TableMapper)。
  • SQL(の入出力パラメタ)と、Bean(POCO) の間のマッピングを行う。

感想

Dapper を使って認証基盤のユーザストアの永続化を実装してみた感想。

  • Dapperは正確には ORM ではないので、

    • 階層構造を持つオブジェクトとストレージ間の同期(セーブ・ロード)処理
    • 複雑なデータアクセス処理
      (特に検索条件や射影などを動的に処理する参照系クエリ)

    などの用途には向かない。

  • ただし RDBMS を NoSQL や X.500 などのストアとコンパチにするような実装の場合は、
    オブジェクト <---> ストア的な実装が必要とされるので、
    用途次第で適合する可能性はあると言える。

適合するシステム・アプリケーション

以下の様なケースでは、Dapperがイイのでは無いかと考える。

  • データストア、データアクセスが単純なケース。
  • サーバーを JSON 吐く土管化するようなケース。
  • RDBMS を NoSQL や X.500 などのストアとコンパチにするようなケース。

分析

データアクセスのフレームワーク、其々に、

  • 生のデータプロバイダ系は SQL 編集処理の柔軟性が高いが、
  • ORM 系は、コーディングが容易化されているが、SQL 編集処理の柔軟性が低い。
    (Bean(POCO) 側が静的なので、SQL 側だけ動的化するインターフェイスを実装できない)

などのトレードオフがある。

このため、アプリケーションの特性によって、
そのデータアクセスのフレームワークが適合するか?しないか?がある。

※ 例えば、基本的な ORM 実装では、オブジェクト操作と永続化操作は切り離されており、
 オブジェクトに対する変更を無造作に更新するため、未更新の列なども更新対象になる。
 (基本的に、未更新列を更新対象から外すなどの、きめ細かな操作はしない。)

補足(この指摘の現在地): 「未更新列まで UPDATE される」という点は、
EF Core では**変更追跡(Change Tracking)**により
変更されたプロパティのみが UPDATE 文に含まれるため、
少なくとも EF Core には当てはまらない
AsNoTracking() で読んだエンティティを Update() した場合は全列更新になる)。

一方、ORM 全般で今なお成立する主要な注意点は以下。

論点 内容
N+1 問題 関連を遅延ロードすると 1 件ごとにクエリが飛ぶ。Include / 明示的な JOIN で回避
発行 SQL の不可視性 何が実行されるか見えにくい。ログで実 SQL を確認する運用が必須
一括更新・削除 行ごとに往復するとバッチで破綻する。ExecuteUpdate / ExecuteDelete(EF Core 7 以降)や生 SQL を使う
動的クエリの柔軟性 元ページの指摘どおり。式ツリーの合成で対応できる範囲を超えると生 SQL が必要

現実的な結論としては、排他ではなく併用が定石。
大半の CRUD は ORM、性能が要る箇所と複雑な参照系は
Dapper か生の ADO.NET というハイブリッド構成が広く採られている。

参考

Java ORマッパー


Tags: 移行, データアクセス, .NET開発, ADO.NET, Entity Framework

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally