DataTable vs BindingList:データソース選定の基準とメリット・デメリット
📋 目次(クリックで展開)
DataGridView にデータを表示・連動させる際、開発者が最初に頭を悩ませるのが「データソースに何を使うか」という問題です。
Windows Forms 開発における二大データソースと言えば、DataTable と BindingList<T> です。どちらを使っても DataGridView にデータを表示できますが、その設計思想や得意・不得意は異なります。
本記事では、実務の画面設計でどちらを選ぶべきかの選定基準と、それぞれのメリット・デメリットを徹底比較します。
DataTable と BindingList の比較表
まずは、両者の違いの比較表を見てみましょう。
| 比較項目 | DataTable | BindingList |
|---|---|---|
| 設計思想 | データベースの「表」をそのままメモリに再現 | C# の「クラス(オブジェクト)」のリスト |
| 型安全性 | 基本は型情報を持たない(文字列で列指定) | 強固な型安全(コンパイル時にエラーを検知) |
| データベースとの親和性 | SqlDataAdapter 等を使い、数行で同期可能 |
Entity Framework などの ORM と相性が良い |
| 標準の並び替え/フィルタ | BindingSource を経由するだけで標準対応 |
そのままでは非対応(自前実装が必要) |
| データの変更状態管理 | 行ごとに「追加・修正・削除」の状態を自動保持 | 変更状態(RowState)の概念はない |
DataTable(データテーブル)
メリット
- データベースとの親和性が高い:SQL で取得したデータを
SqlDataAdapter.Fill(dataTable)とするだけで、1行もループ処理を書くことなくデータを展開できます。画面で編集した内容をデータベースに書き戻す(Update)のも簡単です。 - 並び替え(ソート)や抽出(フィルタ)が強力:
BindingSourceに DataTable を紐付けるだけで、DataGridView のヘッダークリックによる並び替えや、特定の文字でのフィルタリング機能がコーディングなしで利用できます。 - 変更履歴の自動追跡(RowState):DataTable 内のどの行が「新しく追加されたか」、「値が書き換えられたか」、「削除されたか」を記憶してくれます。一括保存ボタンを押したときに「変更があった行だけをデータベースに送る」という処理が標準機能で実装できます。
デメリット
- 型安全ではない(インデックスや文字列指定):値を取得・変更する際、
row["Price"]のように列名を文字列で指定するため、タイポ(打ち間違い)があってもビルド時にエラーにならず、実行して問題に気付くことになります。 - オブジェクト指向(モダンな設計)に不向き:データを「文字列と数字の集まり」として扱うため、ドメイン駆動設計(DDD)や、ビジネスロジックをクラス内に閉じ込めるようなクリーンアーキテクチャの設計に組み込みにくい特性があります。
2. BindingList(バインディングリスト)
メリット
- オブジェクト指向と型安全性:
BindingList<Product>のように、自分で定義したクラスのリストとして扱います。product.Price = 120000;のようにプロパティを直接操作できるため、タイポはコンパイルエラーになり、バグが事前に排除されます。 - クラス内のロジックをそのまま活かせる:「価格が10万円以上なら、自動的に消費税計算のロジックを変える」といったメソッドやプロパティをクラス内に隠蔽(カプセル化)でき、それが DataGridView の表示に連動します。
- データの追加・削除がリアルタイムに画面連動:コード側で
.Add()や.Remove()を行ったタイミングで DataGridView に変更を通知するため、画面をリフレッシュするコードを省けます。
デメリット
- 標準では「並び替え」と「フィルタ」が効かない:通常の BindingList をそのまま DataGridView にバインドしても、ヘッダーをクリックした際の並び替えが動作しません。 実務でソートやフィルタを使いたい場合は、
BindingList<T>を継承した独自のカスタムクラス(SortableBindingList<T>など)を自作して、内部ロジックを実装する必要があります。 - 変更状態を自分で管理する必要がある:DataTable のように「どの行が編集されたか」という状態を持たないため、データベースに保存する際は、全行をループして入れ替えるか、クラス内に
IsDirtyなどのフラグを自前で用意して管理する必要があります。
どちらを使うべきかの選定基準
実務において、どちらを採用すべきかは「システム全体のアーキテクチャ(設計手法)」と「画面に求められる要件」で決定します。
「DataTable」を選ぶケース
- 既存のシステムが ADO.NET(DataSet等)ベースで構築されている
- 画面上で大量のデータをグリッド表示し、ヘッダークリックによるソートや、テキストボックスによるリアルタイム抽出(検索)が求められる
- 編集・追加・削除されたデータを、最後に一括でデータベースに保存したい
「BindingList」を選ぶケース
- Entity Framework (EF Core) などのモダンな ORM を採用している
- ビジネスロジックが複雑で、データを「単なる表」ではなく「振る舞いを持ったオブジェクト」として扱いたい
- 画面が起動した後は選択肢や行数が固定、または並び替え機能が画面要件として不要である
まとめ:適材適所で使い分ける
これまでの記事で解説してきた通り、DataGridView はどちらのデータソースであっても美しく連動させることができます。
「DataTable = データベース直結型・機能多め」、「BindingList = オブジェクト指向型・安全でクリーン」という特性を理解し、構築するシステムの規模やチームの設計ルールに合わせて最適なものを選択してください。
- データのソート・フィルタ・一括更新の手軽さを最優先するなら
DataTable - C# 本来の型安全性を活かし、保守性の高いコードを目指すなら
BindingList<T>
関連記事
それぞれのデータソースに対する具体的なバインド手順は、以下の関連記事で取り上げています。
- DataGridView に DataTable をバインドする(サンプルあり)
- DataGridView:BindingList をバインドする(サンプルあり)
- DataGridView:BindingSource でデータを検索・絞り込む(サンプルあり)
- DataGridView:BindingSource での双方向バインディングと反映タイミングの制御(サンプルあり)
- ComboBox に DataTable をバインドする(実行可能サンプルあり)
💬 コメント