我在下面使用这个:
public static DataTable DataTableJoiner(DataTable dt1, DataTable dt2)
{
using (DataTable targetTable = dt1.Clone())
{
var dt2Query = dt2.Columns.OfType<DataColumn>().Select(dc =>
new DataColumn(dc.ColumnName, dc.DataType, dc.Expression,
dc.ColumnMapping));
var dt2FilterQuery = from dc in dt2Query.AsEnumerable()
where targetTable.Columns
.Contains(dc.ColumnName) == false
select dc;
targetTable.Columns.AddRange(dt2FilterQuery.ToArray());
var rowData = from row1 in dt1.AsEnumerable()
join row2 in dt2.AsEnumerable()
on row1.Field<int>("Code") equals
row2.Field<int>("Code")
select row1.ItemArray
.Concat(row2.ItemArray
.Where(r2 =>
row1.ItemArray.Contains(r2) == false)).ToArray();
foreach (object[] values in rowData) targetTable.Rows.Add(values);
return targetTable;
}
}
此行存在问题:
select row1.ItemArray.Concat(row2.ItemArray.Where(r2 =>
row1.ItemArray.Contains(r2) == false)).ToArray();
似乎是说如果这个值(而不是列)已经存在,请不要包括我。
我正在使用此方法根据两个表共享的列将两个表连接在一起,但我只希望将具有两个表数据的唯一列作为最终结果。
有什么想法吗?
答案 0 :(得分:1)
我不确定我是否理解你的要求100%,但是这个:
row2.ItemArray.Where(r2 => row1.ItemArray.Contains(r2) == false)
将过滤掉恰好出现在表1的任何列中的项目,而不仅仅是您要加入的列。
所以我尝试做的是使用Where
扩展方法的重载来基于索引过滤项目:
// Get the index of the column we are joining on:
int joinColumnIndex = dt2.Columns.IndexOf("Code");
// Now we can filter out the proper item in the rowData query:
row2.ItemArray.Where((r2,idx) => idx != joinColumnIndex)
...
不,等等。此处:
var dt2FilterQuery = from dc in dt2Query.AsEnumerable()
where targetTable.Columns
.Contains(dc.ColumnName) == false
select dc;
您正在过滤掉表2中列出的所有列,其名称也出现在表1中。所以您可能想要的是:
public static DataTable DataTableJoiner(DataTable dt1, DataTable dt2)
{
DataTable targetTable = dt1.Clone();
var dt2Query = dt2.Columns.OfType<DataColumn>().Select(dc =>
new DataColumn(dc.ColumnName, dc.DataType, dc.Expression,
dc.ColumnMapping));
var dt2FilterQuery = from dc in dt2Query.AsEnumerable()
where !targetTable.Columns.Contains(dc.ColumnName)
select dc;
var columnsToAdd = dt2FilterQuery.ToArray();
var columnsIndices = columnsToAdd.Select(dc => dt2.Columns.IndexOf(dc.ColumnName));
targetTable.Columns.AddRange(columnsToAdd);
var rowData = from row1 in dt1.AsEnumerable()
join row2 in dt2.AsEnumerable()
on row1.Field<int>("Code") equals
row2.Field<int>("Code")
select row1.ItemArray
.Concat(row2.ItemArray
.Where((r2,idx) =>
columnsIndices.Contains(idx))).ToArray();
foreach (object[] values in rowData) targetTable.Rows.Add(values);
return targetTable;
}
顺便说一下。我不太明白为什么要在using
语句中包装返回的DataTable。 Imho将你返回给你的呼叫者的对象处理起来是毫无意义的......