比较使用Linq在c#中与主键链接的2个dataTable

时间:2016-06-21 09:55:47

标签: c# linq datatable

我想使用id作为主键,并且必须将2个表与此主键链接。结果必须像这样

  1. 首先检查主键是否存在于第二个表中
  2. 根据密钥
  3. 更新相关数据

    代码:

     DataTable dt1 = new DataTable("Table1");
        dt1.Columns.Add("Id",typeof(int)); 
        dt1.Columns.Add("Name");
        dt1.Columns.Add("Occupation");
    
        DataTable dt2 = new DataTable("Table2");
        dt2.Columns.Add("Id",typeof(int));
        dt2.Columns.Add("Name");
        dt2.Columns.Add("Occupation");
    
        DataTable Final = dt1.AsEnumerable()
                             .Except(dt2.AsEnumerable(), DataRowComparer.Default)
                             .CopyToDataTable();
    
    [I need the result to be like this][1]
    
      [1]: http://i.stack.imgur.com/brqCF.jpg
    
    
    new Code : 
    
    
    
    
    
    
    
    DataTable dtFinal = new DataTable();
    
            DataTable dtNew = new DataTable();
            dtNew.Columns.Add("Id");
            dtNew.Columns.Add("Name");
            dtNew.Rows.Add("1", "Yash Fale");
            dtNew.Rows.Add("3", "Rahul");
    
    
            DataTable dtOld = new DataTable();
            dtOld.Columns.Add("Id");
            dtOld.Columns.Add("Name");
            dtOld.Rows.Add("1", "Yash");
            dtOld.Rows.Add("2", "pops");
    
    
            var addOrUpdateRecords =
                                    (from drNew in dtNew.AsEnumerable()
                                     join drOld in dtOld.AsEnumerable() on drNew.Field<string>("Id") equals drOld.Field<string>("Id") into match
                                     from drOld in match.DefaultIfEmpty()
                                     where drOld == null /* new */ || !DataRowComparer.Default.Equals(drNew, drOld) /* changed */
                                     select drNew).ToList();
                if (addOrUpdateRecords.Any())
                    dtFinal = addOrUpdateRecords.CopyToDataTable();
    
            // i want to add new column like as Status for below condition 
            // for added Records = status : newRecord
            // for updated Records = status : UpdatedRecord
    
    
            //OutPut : ie. dtFinal
            // ID Name Status
            //  1  Yash Fale UpdatedRecord
            //  3  Rahul     newRecord
    

1 个答案:

答案 0 :(得分:2)

用于按某些标准关联两个序列的LINQ运算符称为join

dt1重命名为dtOld,将dt2重命名为dtNew

添加的记录可以通过使用group joindtNew字段上加入dtOldId并过滤dtNew中没有匹配的记录来确定记录在dtOld

var addRecords =
    (from drNew in dtNew.AsEnumerable()
     join drOld in dtOld.AsEnumerable() on drNew.Field<int>("Id") equals drOld.Field<int>("Id") into match
     where !match.Any()
     select drNew).ToList();

请注意,上面会产生List<DataRecord>。当传递的序列为空时,CopyToDataTable调用失败,因此如果您确实需要数据表,请使用以下内容:

var dtAdd = addRecords.Any() ? addRecords.CopyToDataTable() : null;

确定已删除的记录完全相同,只交换了dtOlddtNew

var deleteRecords =
    (from drOld in dtOld.AsEnumerable()
     join drNew in dtNew.AsEnumerable() on drOld.Field<int>("Id") equals drNew.Field<int>("Id") into match
     where !match.Any()
     select drOld).ToList();

最后,可以使用inner join检索修改后的记录,并过滤不同的匹配记录(方便的DataRowComparer.Default可用于比较数据行值):

var updateRecords =
    (from drNew in dtNew.AsEnumerable()
     join drOld in dtOld.AsEnumerable() on drNew.Field<int>("Id") equals drOld.Field<int>("Id")
     where !DataRowComparer.Default.Equals(drNew, drOld)
     select drNew).ToList();

更新:为了完整起见,以下是使用left outer join一次查询新查询和已修改记录的方法,这次使用{{3}}:

var addOrUpdateRecords =
    (from drNew in dtNew.AsEnumerable()
     join drOld in dtOld.AsEnumerable() on drNew.Field<int>("Id") equals drOld.Field<int>("Id") into match
     from drOld in match.DefaultIfEmpty()
     where drOld == null /* new */ || !DataRowComparer.Default.Equals(drNew, drOld) /* changed */
     select drNew).ToList();