我有两个DataTables
: dtChild 和 dtMaster 。
对于 dtChild 中的每一行,我想看看 dtMaster 中是否存在匹配项。此匹配基于特定列。
因此,在上图中,DataTables
都有名为 Col2 和 Col3 的列。这些是我们感兴趣的列。在第二行,我们有匹配。因为 dtMaster 中有一行,其中 Col2 的值等于 Value22 ,而 Col3 的值等于< EM> Value23 。
我想编写一个LINQ查询,为第一行结果返回null
(因为 dtChild 中的第一行没有匹配),第二行返回id dtMaster 中找到的记录(我们假设 dtMaster 在这种情况下也有一个名为Id的主键列)。
N.B。每次运行程序时,列名都会有所不同。所以我们希望我们的LINQ是动态的。此外,匹配列的数量(上例中的2)可以变化。因此,可能存在我们的条件基于5列的值的情况。
答案 0 :(得分:1)
您可以使用:
DataTable dtResult = dtChild.Clone();
foreach(DataRow row in dtChild.Rows)
{
DataRow newRow = dtResult.Rows.Add();
newRow.SetField("Col1", row.Field<string>("Col1"));
DataRow firstmatchingRow = dtMaster.AsEnumerable()
.FirstOrDefault(r => r.Field<string>("Col2") == row.Field<string>("Col2")
&& r.Field<string>("Col3") == row.Field<string>("Col3"));
string col2 = null;
string col3 = null;
if(firstmatchingRow != null)
{
col2 = firstmatchingRow.Field<string>("Col2");
col3 = firstmatchingRow.Field<string>("Col3");
}
newRow.SetField("Col2", col2);
newRow.SetField("Col3", col3);
}
如果您想要一种动态方法,您可以在其中指定两个表的键列,您可以使用它:
string[] keyColumnNames = { "Col2", "Col3" };
DataTable dtResult = dtChild.Clone();
DataColumn[] childColumns = dtResult.Columns.Cast<DataColumn>()
.Where(c => keyColumnNames.Contains(c.ColumnName))
.ToArray();
DataColumn[] masterColumns = dtMaster.Columns.Cast<DataColumn>()
.Where(c => keyColumnNames.Contains(c.ColumnName))
.ToArray();
foreach (DataRow row in dtChild.Rows)
{
DataRow newRow = dtResult.Rows.Add();
newRow.SetField("Col1", row.Field<string>("Col1"));
var matchingRows = dtMaster.AsEnumerable()
.Where(masterRow => !masterColumns.Select(mc => masterRow.Field<string>(mc))
.Except(childColumns.Select(cc => row.Field<string>(cc)))
.Any());
DataRow firstMatchingRow = matchingRows.FirstOrDefault();
foreach(DataColumn col in childColumns)
newRow.SetField(col, firstMatchingRow == null
? null
: firstMatchingRow.Field<string>(col.ColumnName));
}
答案 1 :(得分:0)
未经测试......
class Data<T>()
{
public int Id {get; set;}
public T Value{get; set;}
}
var cols=dtChild.Columns.OfType<DataColumn>().All(c=>c.Name).toList();
var idCol=cols.Single(c=>c=="Id");
var valcols=cols.Where(c=>c!="Id");
var lst=new List<Data>();
var chlds=dtChild.Rows.OfType(DataRow);
chlds.ToList().ForEach(c=>lst.Add(new Data{ Id=c[idCol], Value=null} ); //initialize to null
foreach(var r1 in chlds)
{
foreach(var r2 in dtMaster.Rows.OfType(DataRow))
{
if (r1[idcol]==r2[idCol])
{
forech(var c in valCols)
{
if (r1[c]==r2[c])
{
lst.Single(l=>l.Id==r1[c]).Value= r2[idCol];
break;
}
}
}
}
}