比较两个DataTable并选择不在第二个表中的第一个表记录

时间:2017-03-01 10:59:48

标签: c# winforms linq linq-to-dataset system.data.datatable

我有两个DataTable从两个不同的来源获取数据。我想要一个新的DataTable Table3,其中只有TABLE1行没有匹配的Table2行。我的两个DataTable具有不同的结构,如下所示。但是,它们都共享相同的主键 - CarReg。因此,我想使用CarReg列比较行,并返回Table1中的所有行,但不返回Table2中的行。我返回的Table3 DataTable将具有与Table1相同的结构。

Table1.Columns.Add("CarReg", typeof(string));
Table1.Columns.Add("Site", typeof(string));
Table1.Columns.Add("Route", typeof(double));
Table1.Columns.Add("Driver", typeof(string));
Table1.Columns.Add("StartingDate", typeof(string));

Table2.Columns.Add("CarReg", typeof(string));
Table2.Columns.Add("SITE DESC", typeof(string));
Table2.Columns.Add("Route DESC", typeof(double));
Table2.Columns.Add("Driver", typeof(string));
Table2.Columns.Add("KILOS", typeof(string));

我已尝试过以下内容,但是,我从第一个表Table1获取所有记录。我只需要获取Table1中的记录但不在Table2中。因此,例如,如果Table1有20条记录而Tables2有15条记录,那么我只需要有5条记录。请帮忙。

var recordsNotInB = TableA.AsEnumerable().Select(r =>r.Field<string>("CarReg").Except(TableB.AsEnumerable().Select(r => r.Field<string>("CarReg")));

4 个答案:

答案 0 :(得分:1)

如果您不再了解您的代码,我会想出这个。

var idsFromTableB = TableB.AsEnumerable().Select(tb => tb.Field<string>("CarReg"));
var recordsNotInB = TableA.AsEnumerable().Where(ta => !idsFromTableB.Contains(ta.Field<string>("CarReg")));

答案 1 :(得分:1)

您可以使用哈希集来提高性能并指定比较方法。

var idsFromTableB = new HashSet<string>(TableB.AsEnumerable()
    .Select(tb => tb.Field<string>("CarReg")), StringComparer.OrdinalIgnoreCase);

var recordsNotInB = TableA.AsEnumerable()
    .Where(ta => !idsFromTableB.Contains(ta.Field<string>("CarReg")));

答案 2 :(得分:0)

您可以使用下一个代码段尝试:

        var result = new List<DataRow>();
        //convert to list to avoid multiple enumerations
        var table2List = Table2.AsEnumerable().ToList();

        foreach(var row in Table1.AsEnumerable())
        {
            var matchingRow = table2List.FirstOrDefault(x => x["CarReg"] == row["CarReg"]);

            if(matchingRow == null)
            {
                result.Add(row);
            }
        }  

您应该从Table1获取基于CarReg字段的不在Table2中的DataRows集合。

答案 3 :(得分:0)

好的,这是一个冗长的解决方案,但我已经测试过它并且有效。

我已经通过为每个表创建POCO对象来完成它,然后采用不同之处,因为它比使用容易出错的Table1 [“CarReg”]更容易使用公共属性。

可能有人可以改进此解决方案。

让您的表格由POCO类表示,如:

public class Table1
{
    public string CarReg { get; set; }
    public string Site { get; set; }
    public double Route { get; set; }
    public string Driver { get; set; }
    public string DateString { get; set; }
}

public class Table2
{
    public string CarReg { get; set; }
    public string Site { get; set; }
    public double Route { get; set; }
    public string Driver { get; set; }
    public string Kilos { get; set; }
}

让我们填充数据:

IEnumerable<Table1> data1 = new List<Table1>()
            {
                new Table1() { CarReg = "123ABC", DateString = "20/02/2018", Driver = "Driver 1", Route = 45.45, Site = "England" },
                new Table1() { CarReg = "456ABC", DateString = "20/03/2018", Driver = "Driver 2", Route = 55.45, Site = "Scotland" },
                new Table1() { CarReg = "789ABC", DateString = "20/04/2018", Driver = "Driver 3", Route = 65.45, Site = "Wales" },
            };

            IEnumerable<Table2> data2 = new List<Table2>() {
                new Table2() { CarReg = "123XYZ", Kilos = "34KG", Driver = "Driver 5", Route = 45.45, Site = "Karachi" },
                new Table2() { CarReg = "456ABC", Kilos = "44KG", Driver = "Driver 2", Route = 55.45, Site = "Scotland" },
                new Table2() { CarReg = "789CCC", Kilos = "54KG", Driver = "Driver 7", Route = 65.45, Site = "Hyderabad" },
            };

创建一个包含结果数据的列表:

 List<Table1> oneList = new List<Table1>();

循环以识别Table2中不存在的行

  bool matchFound = false; // an indicator if match is found in table 2

        foreach (var item in data1)
        {
            foreach (var item2 in data2)
            {
                if (item.CarReg != item2.CarReg)
                {
                    matchFound = false;
                }
                else
                {
                    matchFound = true;
                    break;
                }
            }
            if (!matchFound)
            {
                if (!oneList.Contains(item))
                {
                    oneList.Add(item);
                }
            }

        }

希望这有帮助!