美文网首页
C# 两个 DataTable 比较

C# 两个 DataTable 比较

作者: 百里有声 | 来源:发表于2022-04-15 16:08 被阅读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();
            }
        }
    
    

    相关文章

      网友评论

          本文标题:C# 两个 DataTable 比较

          本文链接:https://www.haomeiwen.com/subject/mphqertx.html