.NET > データテーブル


※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

.NET Frameworksバージョン1時代から実装されている、メモリ上で稼働する簡易的なオンメモリデータベースです。

データテーブルを理解しうまく使えるかどうかが、アプリケーション設計において非常に重要な要素となります。
データテーブルにはレコードの追加位置や削除されたレコードを記録されるため、後からそれらの情報を引き出すことができます。
また、ビュー機能を使うことで、任意の条件だけを含んだデータセットを抽出することができます。

DataTableの欠点としては、テーブルのフィールドに型の概念を持ち込めないことです。
スキームの指定時に格納可能なデータの型を設定できますが、これはDataTable内でのみ使用される内部情報(検索や集計、ソートなどの操作で使われる)だけです。
あるレコードのフィールドへのアクセスにはフィールド名を文字列で指定する必要があるので、タイプミスの問題や取得したデータはすべてobject型であり、プログラマが自分で型を調べキャストしなければならない。

使い方

// DataTableを作成
//    - 強い型付けでカラムを定義
//    - FirstNameカラムはstring型
//    - LastNameカラムはstring型
//    - AgeカラムはInt32型
DataTable table = new DataTable();
table.Columns.Add("FirstName", typeof(string));
table.Columns.Add("LastName", typeof(string));
table.Columns.Add("Age", typeof(Int32));
 
// レコードの追加
 
//    - DataRowを使った方法
DataRow row;
row = table.NewRow();
row["FirstName"] = "山田";
row["LastName"] = "太郎";
row["Age"] = 20;
 
//    - DataTable.Rowsにobject[]型でレコードを追加
table.Rows.Add(new object[] {"佐藤","健",23});
 
 
// レコードの参照
DataRow frow = table[0];
string firstName = table[0]["FirstName"]; // 同じ
firstName = frow["FirstName"];            // 
 
// レコードの走査
foreach(DataRow crow in table.Rows) {
	// DataRowを使ってすべての行に対して処理
}
 
// フィルタリング(DataViewの使用)
DataView view = table.DefaultView;
view.RowFilter = "Age > 18"; // Ageフィールドの値が18以上のものだけを表示
 
for(int i=0;i<view.Count;i++){
	DataRow row = view[i];
}

スキーマの作成

DataColumnを定義することで、DataTableにデータ構造のスキーマを定義します。
スキーマを与えると、正しくない値を含んだレコードをDataTableに追加した時にエラーの検出ができます。

DataTypeプロパティはカラムが格納することができる型を指定します。 DataColumn.DataTypeを指定することで強い型付けされたDataTableを作成することができます。
ただし、プログラマが作成した独自の型は指定することはできません

ReadOnlyプロパティ
レコードの追加時のみ値を設定することができ、以降は読み取り専用となります。
AutoIncrementプロパティ
DataTypeがint型の場合に、レコードが追加されるたびに「0」から

インクリメントされた値を自動的に格納していきます。 AutoIncrementSeed や AutoIncrementStep と併用することで インクリメントの開始値や加算値を調整できます。

DefaultValueプロパティ
カラムの初期値を設定します。
// カラムへスキームを設定するコード例
//     - Decimal型
//     - Nullを許容しない
//     - コメントに「Price」
//     - カラム名は「Price」
//     - 値が未設定の場合は「25」とする
DataColumn column = new DataColumn(); 
column.DataType = System.Type.GetType("System.Decimal"); 
column.AllowDBNull = false; 
column.Caption = "Price"; 
column.ColumnName = "Price"; 
column.DefaultValue = 25;

DataTableからのデータ取得方法

データの抽出

DataTable table = new DataTable();
// ... tableの初期化
 
var rows = table.Select("Message = 'Test Message' OR FirstName like 'T%'","Message");

DataTable.Selectは遅いです。レコード数だけでなくフィールド数や各フィールドの型によって急激にパフォーマンスが悪くなることがあるので、使用する際はパフォーマンスを意識する必要があります。

データの抽出(LINQ)

C#3以降ではLINQを使用してDataTableやコレクションからデータを探すことができます。
パフォーマンスではLINQを使用する方法がもっとも早い(DataTable.Selectを使うよりも2倍以上早い)。

DataTable table = new DataTable();
// ... tableの初期化
 
var rows = (
	from row in table.AsEnumerable()
	let column0 = row.Field<string>("Message")
	let column1 = row.Field<string>("FirstName")
	where column0 == "Test Message" || column1.StartsWith("T")
	orderby column0
	select row
).ToArray();

データの集計

DataTableを駆使してデータの集計を行った方法を下記サイトで紹介しています。

ただ、DataViewを使ったり、重複を削除した後に集計を自分で計算するなど、スマートでないというイメージがあります。

C#3以降ならばLINQを使ってうまくできるハズですが。

DataTableの機能

ある状態からの変更点を取得する(トランザクション機能)

AcceptChanged()を呼び出してからの変更点をDataTableは記録しています。
GetChanged()を使って変更点を取得できます。引数に指定したものによって、削除されたレコード・追加されたレコード・変更されたレコードなどを取得できます。

DataTable table = new DataTable();
// ... テーブルの初期化
 
table.AcceptChanges(); // ここから
 
// ... テーブルの処理
 
DataTable deleted = table.GetChanged(DataRowState.Deleted); // 削除されたレコードが含まれたテーブル
if( daleted != null ) {
	// 削除されたレコードに対する処理を行う
 
	// deleted.RejectChanges()を呼び出すことで、この操作を無効にすることもできる。
}

読んでいる本


Effective C#

QLOOKアクセス解析

ここを編集