比较数据表并返回不匹配的行

时间:2015-05-22 15:39:36

标签: c# asp.net .net datatable

我正在尝试比较两个数据表并捕获差异的第三个数据表。

DataTable one = new DataTable();
            one.Columns.Add("ID");
            one.Columns.Add("PCT");
            one.Rows.Add("1", "0.1");
            one.Rows.Add("2", "0.2");
            one.Rows.Add("3", "0.3");
            gvone.DataSource = one;
            gvone.DataBind();
            DataTable two = new DataTable();
            two.Columns.Add("ID");
            two.Columns.Add("PCT");
            two.Columns.Add("OldPCT");
            two.Rows.Add("1", "0.0", "0");
            two.Rows.Add("2", "0.1", "0");
            two.Rows.Add("3", "0.9", "0");
            two.Columns.Remove("OldPCT");
            gvtwo.DataSource = two;
            gvtwo.DataBind();
            DataTable dt3 = two.AsEnumerable().Except(one.AsEnumerable()).CopyToDataTable();
            var diffName = two.AsEnumerable().Select(r => r.Field<string>("PCT")).Except(one.AsEnumerable().Select(r => r.Field<string>("PCT")));
            if (diffName.Any())
            {
                DataTable Table3 = (from row in two.AsEnumerable()
                                    join name in diffName
                                    on row.Field<string>("PCT") equals name
                                    select row).CopyToDataTable();
            }

现在我在表3中的结果应该是数据表2中的所有行。因为价值观不匹配。但它只返回数据表2的第1行和最后一行。但我需要得到表2的所有行。如何订购行并进行比较。

2 个答案:

答案 0 :(得分:0)

循环遍历每个数据表的行,然后遍历该循环中的每个列以比较各个值。

此处示例:

http://canlu.blogspot.com/2009/05/how-to-compare-two-datatables-in-adonet.html

答案 1 :(得分:0)

试试这个解决方案。

// Create a DataTable
DataTable one = new DataTable();
one.Columns.Add("ID", typeof(int));
one.Columns.Add("PCT", typeof(double));
one.PrimaryKey = new DataColumn[] { one.Columns["ID"] };
one.Rows.Add(1, 1.0); // Occur in two, same
one.Rows.Add(2, 2.0); // Occurs in two, but different
one.Rows.Add(3, 3.0); // Not in two 
one.Rows.Add(5, 5.0); // Occur in two, same

// Create a second DataTable
DataTable two = new DataTable();
two.Columns.Add("ID", typeof(int));
two.Columns.Add("PCT", typeof(double));
two.PrimaryKey = new DataColumn[] { two.Columns["ID"] };
two.Rows.Add(1, 1.0); // Occur in one, same
two.Rows.Add(2, 2.1); // Occurs in one, but different
two.Rows.Add(4, 4.0); // Not in one
two.Rows.Add(5, 5.0); // Occur in one, same

// Perform the Except 
// one: whose elements that are not in second will be returned.
// two: whose elements that also occur in the first sequence will cause those elements to be removed from the returned sequence.
DataTable oneTwo = one.AsEnumerable().Except(two.AsEnumerable()).CopyToDataTable();
DataTable twoOne = two.AsEnumerable().Except(one.AsEnumerable()).CopyToDataTable();

// Sort the results by "PCT" 
oneTwo.DefaultView.Sort = "PCT DESC";
twoOne.DefaultView.Sort = "PCT DESC";

// For each row (one except two)
foreach (DataRowView dr in oneTwo.DefaultView)
{
    string id = dr["ID"].ToString();
    string pct = dr["PCT"].ToString();
}

// Returns four rows
// 5, 5
// 3, 3
// 2, 2
// 1, 1  

// For each row (two except one)
foreach (DataRowView dr in twoOne.DefaultView)
{
    string id = dr["ID"].ToString();
    string pct = dr["PCT"].ToString();
}

// Returns four rows
// 5, 5
// 4, 4
// 2, 2.1
// 1, 1  


// Another Solution
// Or you can just do a WHERE
DataTable three = two.AsEnumerable().Where(r2 => !one.AsEnumerable().Any(r1 => r1.Field<int>("ID") == r2.Field<int>("ID") &&
                                                                                r1.Field<double>("PCT") == r2.Field<double>("PCT")))
                                    .CopyToDataTable();


three.DefaultView.Sort = "PCT DESC";

// For each row (based on where)
foreach (DataRowView dr in three.DefaultView)
{
    string id = dr["ID"].ToString();
    string pct = dr["PCT"].ToString();
}

// Returns two rows
// 4, 4  
// 2, 2.1