C# 两个 DataTable 比较

2022-04-15  本文已影响0人  百里有声

经常有对两个DataTable进行比较的需求,比如通过C# winform或者 asp.net 将Excel导入到数据库的过程中,
可能需要将现有数据从数据库里拿出来缓存到DataTable(清表重新插入不在此讨论范围),同时将需要导入的Excel的数据解析成DataTable,然后进行一下比对,确认是添加还是修改。
比较的过程中,可能只比较一个字段,也可能比较多个,甚至能比较不同的字段
(多字段比较时,是AND的关系,同时满足认为是相同记录)
在要导入的Excel生成的DataTable里增加一个Flag字段,保存比较的结果(表示是否存在此记录)。

   class Program
    {
        //相同的字段名生成比较委托列表
        static List<Func<DataRow, DataRow, bool>> GenerateCheck(List<string> checkColumns)
        {
            var checkConditons = new List<Func<DataRow, DataRow, bool>>();
            foreach (string column in checkColumns)
            {
                checkConditons.Add((s, t) => s[column].ToString().Equals(t[column].ToString()));
            }
            return checkConditons;
        }

        //不同的字段名生成比较委托列表,用Tuple映射不同的字段名
        static List<Func<DataRow, DataRow, bool>> GenerateCheck(List<Tuple<string, string>> checkColumns)
        {
            var checkConditons = new List<Func<DataRow, DataRow, bool>>();
            foreach (var column in checkColumns)
            {
                checkConditons.Add((s, t) => s[column.Item1].ToString().Equals(t[column.Item2].ToString()));
            }
            return checkConditons;
        }

        //要导入的数据
        static DataTable GetSource()
        {
            DataTable target = new DataTable();
            target.Columns.Add("ID", typeof(Int32));
            target.Columns.Add("Name", typeof(String));
            target.Columns.Add("Age", typeof(Int32));
            target.Columns.Add("Flag", typeof(Int32));   //增加一个Flag字段保存结果
            target.Rows.Add(new object[] { 1, "张三", 20, 0 });
            target.Rows.Add(new object[] { 2, "李四", 45, 0 });
            target.Rows.Add(new object[] { 3, "王五", 40, 0 });
            target.Rows.Add(new object[] { 4, "马六", 21, 0 });
            target.Rows.Add(new object[] { 20, "张三", 1, 0 });
            target.Rows.Add(new object[] { 25, "李四", 2, 0 });
            return target;
        }


        //原数据库数据
        static DataTable GetTarget()
        {
            DataTable source = new DataTable();
            source.Columns.Add("ID", typeof(Int32));
            source.Columns.Add("Name", typeof(String));
            source.Columns.Add("Age", typeof(Int32));

            source.Rows.Add(new object[] { 1, "张三", 20 });
            source.Rows.Add(new object[] { 2, "李四", 25 });
            source.Rows.Add(new object[] { 3, "王五", 21 });
            source.Rows.Add(new object[] { 4, "马六", 21 });
            return source;
        }

        //相同的字段名
        static void SameColumnName()
        {
            DataTable source = GetSource();
            DataTable target = GetTarget();
            var checkColumns = new List<string> { "ID", "Name", "Age" };
            var checkCondtions = GenerateCheck(checkColumns);
            foreach (DataRow s in source.Rows)
            {
                var result = target.AsEnumerable().Where(t => checkCondtions.All(check => check(s, t)));
                if (result.Any())
                {
                    s["Flag"] = 1;
                }
            }
            source.AsEnumerable().Where(item => item["Flag"].ToString() == "1").ToList().ForEach(item => Console.WriteLine("  " + item["Name"].ToString()));
        }
        //不同的字段名
        static void DiffrentColumnName()
        {
            DataTable source = GetSource();
            DataTable target = GetTarget();
            var checkColumns = new List<Tuple<string, string>>();
            checkColumns.Add(Tuple.Create("ID", "Age"));
            checkColumns.Add(Tuple.Create("Name", "Name"));
            var checkCondtions = GenerateCheck(checkColumns);
            foreach (DataRow s in source.Rows)
            {
                var result = target.AsEnumerable().Where(t => checkCondtions.All(check => check(s, t)));
                if (result.Any())
                {
                    s["Flag"] = 1;
                }
            }
            source.AsEnumerable().Where(item => item["Flag"].ToString() == "1").ToList().ForEach(item => Console.WriteLine("  " + item["Name"].ToString()));
        }

        static void Main(string[] args)
        {
            Console.WriteLine("  ");
            SameColumnName(); //"ID", "Name", "Age" 同时满足的只有 张三 马六 两条记录
            Console.WriteLine("==========================");
            DiffrentColumnName();//"Name"相同,源数据的ID和目标数据的Age相等的只有 张三 李四 两条记录
            Console.ReadLine();
        }
    }

上一篇下一篇

猜你喜欢

热点阅读