いろいろ備忘録日記

主に .NET と Python絡みのメモを公開しています。

ADO.NET入門記-020 (DataTableに追加された拡張メソッド)(System.Data.DataTableExtensions, AsEnumerable, CopyToDataTable)


.NET Framework 3.5になって、DataTableに以下の拡張メソッドが用意されました。

  • AsDataView
  • AsEnumerable
  • CopyToDataTable


尚、これらの拡張メソッドは、System.Data.DataTableExtensionsクラスに定義されています。
厳密にはCopyToDataTableメソッドはIEnumerable系の拡張メソッドなんですが、DataTableと
合わせて利用するのでここに挙げてます。


AsEnumerableメソッドを利用するとDataTableにLinqを実行することが出来ます。
例:

IEnumerable<DataRow> query = from row in table.AsEnumerable()
                             where 条件
                             select row;

みたいな感じです。


で、現実的によく行うのが抽出した結果をまた別のDataTableとして
利用するというパターンです。
その場合に、CopyToDataTableメソッドが利用できます。
CopyToDataTableメソッドのメソッドシグネチャは以下のようになっています。

DataTable CopyToDataTable<T>(this IEnumerable<T> source) where T : DataRow

つまり、TにはDataRowかそのサブクラスしか許容されません。
AsEnumerableが返却するのはIEnumerableを返すので
その結果のクエリはそのままCopyToDataTableがコールできるようになってます。

DataTable newTable = query.CopyToDataTable();

これで、新しいデータテーブルの出来上がりです。


以下そのサンプルです。

#region DataTableExtensionsSample-01

    public class DataTableExtensionsSample01 : IExecutable{

        public void Execute(){
            DataTable table = BuildSampleTable();
            PrintTable("Before:", table);

            IEnumerable<DataRow> query = from row in table.AsEnumerable()
                                         where (row.Field<int>("COL-1") % 2) != 0
                                         select row;

            DataTable newTable = query.CopyToDataTable();
            PrintTable("After:", newTable);
        }

        DataTable BuildSampleTable(){
            DataTable table = new DataTable();

            table.BeginInit();
            table.Columns.Add("COL-1", typeof(int));
            table.Columns.Add("COL-2");
            table.EndInit();

            table.BeginLoadData();
            for(int i = 0; i < 5; i++){
                table.LoadDataRow(new object[]{i, (i + 1).ToString()}, true);
            }
            table.EndLoadData();

            return table;
        }

        void PrintTable(string title, DataTable table){
            Console.WriteLine(title);

            foreach(DataRow row in table.Rows){
                Console.WriteLine("\t{0}, {1}", row[0], row[1]);
            }

            Console.WriteLine();
        }
    }
#endregion


補足:ちなみに、AsEnumerableを使わない場合でも

from DataRow row in table.Rows
where 条件
select row;

って書き方でもいけます。どちらを使うかは個人の好みですね。

from row in table.Rows

という書き方はエラーとなります。Rowsが返すDataRowCollectionがIEnumerable
実装していないからです。