いろいろ備忘録日記

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

ADO.NET入門記-022 (DataRow同士の比較)(System.Data.DataRowExtensions, SequenceEqual, All, AsEnumerable)


.NET Framework 3.5より、System.Data.DataSetExtensions名前空間に以下のクラスが追加されています。

System.Data.DataRowComparer


名前の通り、DataRow用のComparerです。
これまで、DataRowを比較する場合は各列の値を全て手動で見て一致か不一致か否かを
確認していましたが、これからはこれを利用すると楽に比較処理が行えます。


このクラスは、シールクラスとなっており派生させる事は出来ません。
型引数のTRowには、ほとんどの場合DataRowを渡す事になります。


また、このクラスにはpublicなコンストラクタが存在しません。Defaultプロパティより
インスタンスを取得します。


Equalsメソッドを利用するとDataRowを比較出来ますが、通常よくあるパターンが
全行が一致している場合を確認する事が多いと思います。その場合は
DataTableの拡張メソッド AsEnumerableとIEnumerable.SequenceEqual拡張メソッドを利用すると
一発で比較が出来ます。

table1.AsEnumerable().SequenceEqual(table2.AsEnumerable(), DataRowComparer<DataRow>.Default);


以下、サンプルです。

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;

namespace DataRowComparerSample {

    class Program {

        public void Execute() {
            //
            // 2つのデータテーブルを作成.
            //
            DataTable table1 = new DataTable();
            DataTable table2 = new DataTable();

            InitializeColumns(table1);
            InitializeColumns(table2);

            FillRows(table1);
            FillRows(table2);

            ////////////////////////////////////////////////////////
            //
            // 各行データを比較.
            //
            // SequenceEqualを利用して全行一発比較.
            IEnumerable<DataRow> enumerable1 = table1.AsEnumerable();
            IEnumerable<DataRow> enumerable2 = table2.AsEnumerable();

            bool isAllRowEquals = enumerable1.SequenceEqual(enumerable2, DataRowComparer<DataRow>.Default);

            Console.WriteLine("全行のデータが同じ? => {0}", isAllRowEquals);

            //
            // 一行ずつ比較.
            //
            DataRowComparer<DataRow> comparer = DataRowComparer<DataRow>.Default;
            List<bool>               results  = new List<bool>();
            for(int i = 0; i < table1.Rows.Count; i++) {
                results.Add(comparer.Equals(table1.Rows[i], table2.Rows[i]));
            }

            Console.WriteLine("各行のデータが同じ? => {0}", results.All( (isEqual) => { return isEqual; }));
        }

        #region Helper Methods
        protected void InitializeColumns(DataTable table) {

            table.Columns.Add("Id");
            table.Columns.Add("Name");
            table.Columns.Add("Age", typeof(int));
        }

        protected void FillRows(DataTable table) {

            try {
                table.BeginLoadData();

                for(int i = 0; i < 10; i++) {
                    table.LoadDataRow(new object[] { i, string.Format("name-{0}", i), (i + 10) }, true);
                }
            } finally {
                table.EndLoadData();
            }
        }
        #endregion

        static void Main(string[] args) {
            (new Program()).Execute();

            Console.WriteLine(string.Empty);
            Console.WriteLine("Press Any Key to Exit....");
            Console.Read();
        }
    }
}

================================
過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。