-
Notifications
You must be signed in to change notification settings - Fork 0
MS_ADONETVsORM
- 戻る(データアクセスのいろいろ、VS系コンテンツ)
- ADO.NET vs ORM (Entity Framework, Dapper)
ADO.NET、Entity Framework、Dapper、
その他の選択肢のどれを選ぶべきか?
トレードオフがあるので、新しい技術を使っておけばイイという訳には行かない模様。
SQL を使用して、二次元表形式の論理データを自由に取得できる。
Bean(POCO) に ORM ではなく、論理データ独立な二次元表(DataSet、DataTable)を使用できる。
-
DataAdapterはDataSetオブジェクトとデータ ソース間のブリッジとして機能する。 -
DataSetの機能が必要ない場合は、DataReaderを使用したほうが性能が向上する。 -
非接続型データアクセスを実行する場合は
DataSetを使用する。- データをローカルにキャッシュし操作する場合。
- サーバーで取得・更新、クライアントで編集等、
物理境界を超えてデータを持ち回って処理を行う場合。 - Windows フォーム コントロールと連結し、対話的に編集をする場合など。
DataSet
├DataRelationCollection
├ExtendedProperties
└DataTableCollection
└DataTable
├DataColumnCollection─DataColumn─ExtendedProperties
├PrimaryKey
├Constraints
├ChildRelations
├ParentRelations
├ExtendedProperties
├DataView
├DataRowCollection─DataRow
実装は、それ程、難しくない(AutoMapper)。
-
情報系システム
- 多種・多様なビュー(二次元表形式の論理データ)にアクセスする。
- 参照先のテーブルや取得するカラムを動的に変更するようなシステム。
-
基幹系システム
- 複雑なデータアクセスに対応する柔軟性と、
大量データの処理に対応するパフォーマンスを両立させる必要があるシステム。 - 参照したビュー(二次元表形式の論理データ)を元に更新処理を行なうシステム。
- 複雑なデータアクセスに対応する柔軟性と、
移行メモ(誤字): 元ページの「複雑なデータクセス」は「データアクセス」の誤記。
ORM 的なソリューションだが、
今となっては、中途半端で、あまり利用されていない。
- ADO.NETのラッパーライブラリ。
-
非接続型データアクセスの
DataSetが前提。
JOIN などもサポートしているもよう(下記参照)なので、
頑張れば、情報系システム、基幹系システムへの応用も可能と思われる。
- 参考
- Join を使用して TableAdapter を更新する (C#) | Microsoft Learn
https://learn.microsoft.com/ja-jp/aspnet/web-forms/overview/data-access/advanced-data-access-scenarios/updating-the-tableadapter-to-use-joins-cs
- Join を使用して TableAdapter を更新する (C#) | Microsoft Learn
移行メモ(誤字): 元ページの「JION」は「JOIN」、
「中途半場」は「中途半端」の誤記。
補足(最新化): 型付き
DataSet/TableAdapterは
.NET Core 以降のデザイナ サポートが無く、新規開発では使われない。
DataSet/DataTable自体は .NET でも利用可能だが、
既存資産の保守用と考えるのが妥当である。
動的パラメタライズド・クエリ(OTR_DynamicParameterizedQuery.md)
- SQL 編集処理が複雑になるエンプラのドメインで使える。
- SQL 定義をパラメタセットによって編集したい(S2Dao や iBATIS のように)。
- メソッド(= LINQ のメソッド ベースのクエリ構文
(メソッドチェーンやラムダ式))でクエリ編集という方式は、
エンプラのドメインに必要とされる柔軟性が足りない。
- 基本的に SQL を使用せず、概念スキーマに準拠したオブジェクトにデータをストアする。
- プログラム側のデータの持たせ方が「2 次元表」 vs Bean(POCO) と、根本的に異なる。
Entity Frameworkは高機能で複雑なため、
ORM 自体の問題と、切り分けが難しい別の問題を持っている。
以下のような、3 つの開発スタイル(Entity Framework)がある。
-
モデルファースト
- 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は単純な分、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 というハイブリッド構成が広く採られている。
-
レガシーシステムとつきあう - Sansan Builders Box
https://buildersbox.corp-sansan.com/entry/2019/10/23/110000 -
Entity Framework VS LINQ to SQL VS ADO.NET with stored procedures? - Stack Overflow
http://stackoverflow.com/questions/2698151/entity-framework-vs-linq-to-sql-vs-ado-net-with-stored-procedures
-
Java OR マッパー選定のポイント #jsug
https://www.slideshare.net/masatoshitada7/java-or-jsug -
Hibernate はどのようにして私のキャリアを破滅寸前にしたか | To Be Decided
https://www.kaitoy.xyz/2017/02/23/how-hibernate-ruined-my-career/
Tags: 移行, データアクセス, .NET開発, ADO.NET, Entity Framework
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。