DataSet vs カスタムエンティティ

.NETを用いた業務アプリケーション開発において、データベースとのデータの受け渡しにDataSetかカスタムエンティティクラスを用いるか過去さまざまな議論が色々な箇所で行われていますが、傾向としてJava界から転向して来た場合にはカスタムエンティティに慣れていることもありDataSetが嫌われている気がします。

VisualStudioのデザイナが生成するTableAdaptorがいけてないとか(これには同意)、プレーンなオブジェクトではないためNGとか色々主張がありますがそもそも全ての要求を満たす物は存在しませんしVisualStudio・.NETFramework・サードパーティコンポーネントがDataSetを優先的にサポートしているため上手く使いこなせばよいのではないかと思っています。

.NETを使い始めた当初DataSetの機能が良く判らず、ADO-RecordSetと比較して冗長な部分が多くて嫌気が差しカスタムエンティティクラスを使う方向へ一度傾きかけたが、VBから移行してきたメンバーで構成されるプロジェクトではそもそもカスタムエンティティクラスを使う概念が判らずRecordSetの置き換えとしてDataSetを使うケースが圧倒的に多い。

嫌々ながらDataSetを中心とした構成を調査するに従い完璧には遠いが大抵の利用ケースで70〜80点をとれる良く考えられている技術だと考えが改まった。

具体的には

DataSetの長所・短所

○VisualStudioのデザイナで生成可能
○レコード毎にデータの状態を保持
○メモリ上でソート、クエリ、フィルタリング処理が可能
○メモリ上の更新操作をコミット、ロールバック可能
XMLスキーマとデータをエクスポート、インポート可能
○型指定した場合は集計値項目などDBスキーマとは異なるカスタム項目を保持可能
○型指定した場合はDBへ送信前に参照整合性検証などの論理検証が可能
○階層構造を持ったコントロール(ツリーやN次元グリッド)にDataRelationでDatabind可能
○DataAdaptorで容易に操作が可能
○規定でシリアル化対応
○DataBaindで更新、ソートに自動対応
○データ操作時にコールバックされるイベントのエントリポイントが豊富

×他のプラットフォームと相互連携がし難い
×DBカラムをプリミティブ型にしかマップ不可能
×オーバーヘッドが大きい
×型指定していない場合は方情報が失われコンパイルチェック不可能
×Partialクラスで緩和されたが拡張性・再利用がいまいち
×非常に複雑なデータ構造には対処しにくい

カスタムエンティティクラスの長所・短所

○他のプラットフォームと相互連携が容易
○非常に複雑なデータ構造にも対処可能
○DBカラムを疎粒度のオブジェクト型にマップ可能
○オーバーヘッドが小さい
○上手く作れば拡張性・再利用が向上する
○BindingSourceで更新系バインド対応など利用しやすくなったがソートは実装が必要

×コンストラクタ、シリアル化、Equals、HashCode、ToStringをオーバーオード・ライドする必要がある
×標準以外のジェネレータを用意する必要がありキチンと出力する決定的な物がない
×メモリ上でソート、クエリ、フィルタリング処理を実装するのは大変
×レコード毎にデータの状態を保持するDirtyチェックロジックを実装するのは大変
×DataRelationで自動展開するコントロールに対応出来ない

キリがないので辞めておくが大体各々の長所・短所が逆転しているのが判ってもらえるだろうか?

現在の考えとしては、パーケージ製品の開発ではなく小中規模の業務アプリを構築する場合の使い分けの基準としては更新系として扱うデータは型指定したDataSet、参照系で単純なリスト表示はオーバーヘッドの少ないカスタムエンティティクラスのコレクションとしプレゼンテーション層でのソートに対応するならDataSetの方が楽なので用件に応じて判断する。
 ClickOnceのオフライン実行やデータキャッシュとして使う場合はDataSet、Webサービスなど相互連携が必要な箇所はカスタムエンティティとする。
 ClickOnceでリソース系は一旦DBから取得したDataSetからXML出力してディスクへ保存しておき
通常はXMLからリストアしバージョンが更新された場合だけDBからDataSetへ反映するとか更新系の処理を幾つかのRowに行いDataSet上で整合性検証を実行した上で、実際に更新されたデータのみを抽出してWebサービス経由で複数の更新行をバッチ転送し楽観的同時実行制御で撥ねられたRowを識別&最新取得を行ってリトライする処理をカスタムエンティティクラスで実装するのは非常に困難だがDataSetはそのような処理を意図した機能がはじめから用意されている。

複雑なデータモデルをカスタムエンティティクラスでDomainModelとして表現しその資産価値が重要となるようなパッケージ製品の開発等はDataSetの出番が少なくなるだろうが通常の利用ケースにおいては稀なのではないかと思う。少なくとも私の携わる案件はそうだ。
オブジェクト指向の観点で綺麗じゃないとかそんな事は重要ではなく、決められた期限や予算の中で現実のプロジェクトをこなすためには上手に使い分ければ良いということですね!