【C#】DataTable にLinqを使うと、めっちゃ便利!5選

当ページのリンクには広告が含まれています。

一覧形式のデータを保持するのに便利なDataTableクラスですが、これにLinqを使うと、ループでごちゃごちゃやっていた処理が、たった1行で済んでしまいます。

今回は、DataTableを扱う上で、知っておくと便利なLinqの使い方をご紹介します。

ちなみに、この記事ではカラムの事を列と表現しています。

目次

便利な使い方

これから紹介するサンプルソースは、 dt という名前のDataTableインスタンスが、既に出来上がっているという前提です。

任意の列を配列に変換して返す

全ての列を取り出す場合は、次の様に書きます。

dt.AsEnumerable().Select(抽出対象).ToArray()

//全ての行の製品名の内容を配列にして取り出す
var result = dt.AsEnumerable().Select(i=>i["製品名"]).ToArray();

dt.AsEnumerable() と書きましたが、これは dt.Rows.Cast<DataRow>().Select ~ のようにDataTableを DataRow にキャスト(型変換)する記述でもOKです。

//Cast<DataRow> を使った書き方
var result = dt.Rows.Cast<DataRow>().Select(i=>i["製品名"]).ToArray();

任意の列に値を代入する

特定の列に値を代入する(置き換える)場合は、次の様に書きます。

dt.AsEnumerable().Select(代入式).ToArray()

ポイントは末尾のToArray() です。

これが無いと内部的に処理はしてくれるものの、DataTableへの反映(書き戻し)が行われませんのでご注意ください。

ちなみに、ToArray()の代わりに ToList() でもOKです。

//全ての行の価格を35000円に置き換える
dt.AsEnumerable().Select(i=>i["価格"] = "35000").ToArray();

DataTableの全ての列名を配列で返す

DataTableをDataColumnでキャストするとSelectの中で列名が参照できますので、これを利用します。

dt.Columns.Cast<DataColumn>().Select(DataColumnから取り出したいプロパティ).ToArray()

実際のサンプルは次の様になります。

//全ての列名を配列で返す
var result = dt.Columns.Cast<DataColumn>().Select(i=>i.ColumnName).ToArray();

ColumnNameの代わりにDataType を指定すると、全ての列のデータ型が取得できます。

DataTableの全ての列名を変更する

DataTableの列名を変更することも可能です。

dt.Columns.Cast<DataColumn>().Select(代入式).ToArray()

//全ての列名に含まれているアンダースコアを抹消する
dt.Columns.Cast<DataColumn>().Select(i=>i.ColumnName = i.ColumnName.Replace("_","")).ToArray();

条件を満たす行だけ抜き出してDataTableを作成する

特定の条件の行を抜き出したい場合、Where を使いますが、最後に CopyToDataTable() を付けてあげることで、抽出した結果からDataTableを作成してくれます。

dt.AsEnumerable().Where(抽出条件).CopyToDataTable()

//製品名に"10世代"という文字が含まれている行を抜き出してDataTableを作成する
DataTable result = dt.AsEnumerable().Where(i=>i["製品名"].ToString().Contains("10世代")).CopyToDataTable();

同様のことはDataViewクラスを使っても出来ますが、3行になってしまいます。

//DataView の RowFilter を使ってデータを抜き出し、新しくDataTableを作成する
var dv = new DataView(dt);
dv.RowFilter="製品名 like '%10世代%'";
DataTable result = dv.ToTable();

無理やり1行に書く事も出来ます。

//上記と同じ内容を1行で書くなら、次のようになる
DataTable reslut = new DataView(dt){ RowFilter="製品名 like '%10世代%'"}.ToTable();

処理速度は遅いですが、DataTableのSelect()メソッドでデータを抜き出して、CopyToDataTable()メソッドでDataTableにする方法もあります。

こちらはDataViewに比べて素直な書き方になります。

//DataTableに備わっているSelectメソッドによる抽出
DataTable result = dt.Select("製品名 like '%10世代%'").CopyToDataTable();

Linqの処理速度は高速ですが抽出条件の記述が煩雑になるので、場合によって使い分けが必要になります。

データ抽出の速度比較

LinqのWhere、DataViewのRowFilter、DataTableのSelectのそれぞれの方法について、簡単に速度を比較してみました。

ます小規模なDataTable(218行、12列)から、指定した条件で17行のデータを抽出した場合、LinkのWhereが最も速く、DataView.RowFilterが最も遅い結果となりました。

218行×12列のDataTbleから17行を抽出する場合(100回の平均時間)
Linq.Where
0.0590922 ms
DataTable.Select
0.1409331 ms
DataView.RowFilter
0.1990314 ms

次に、比較的大きなDataTalbe(10万行、12列) から、12444行のデータを抽出した場合も、LinkのWhereが最も速く、DataView.RowFilterが最も遅い結果となりました。

10万行×12列のDataTbleから12444行を抽出する場合(100回の平均時間)
Linq.Where
37.353736 ms
DataTable.Select
76.593718 ms
DataView.RowFilter
115.459477 ms

以上様の結果から、DataTableの規模に関係なく Linq が最も速く、2番目に DataTable のSelectメソッド、一番遅いのが DataViewのRowFilter という結果となりました。

LinkのWhereの処理速度は、DataViewのRowFilterに比べて、小さなDataTableでは3倍以上、比較的大きなDataTableで2倍以上も高速であるという結果になりました。

まとめ

いかがでしたでしょうか。

Linqを使うと今までforループで数行記述が必要だった抽出処理が1行で書けてしまいます。

また、指定条件によるデータ抽出では、Linqが他の方法に比べて2~3倍速いということも分かりました。

あまり複雑な記述はよけいに見難くなりますが、単純なものだと可読性も上がります。

Linqが使えるところは、どんどん使っていきましょう。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次