C# 从两个datatable中查找公共列并在LINQ中使用这些列作为连接条件

C# 从两个datatable中查找公共列并在LINQ中使用这些列作为连接条件,c#,linq,datatable,ado.net,C#,Linq,Datatable,Ado.net,我有两个数据表,它们是完全动态的。这些将在运行时生成。现在我想通过查找公共列来连接这些表 请查看下面的代码以了解更多信息 public DataTable DataTableJoiner(DataTable dt1, DataTable dt2) { using (DataTable targetTable = dt1.Clone()) { var dt2Query = dt2.Columns.OfType<DataColumn>().Select(d

我有两个数据表,它们是完全动态的。这些将在运行时生成。现在我想通过查找公共列来连接这些表

请查看下面的代码以了解更多信息

public 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>("ID") equals row2.Field<int>("ID")
                    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;
    }
}
公共DataTable DataTableJoiner(DataTable dt1、DataTable dt2)
{
使用(DataTable targetTable=dt1.Clone())
{
var dt2Query=dt2.Columns.OfType().Select(dc=>
新的DataColumn(dc.ColumnName、dc.DataType、dc.Expression、dc.ColumnMapping));
var dt2FilterQuery=来自dt2Query.AsEnumerable()中的dc
其中targetTable.Columns.Contains(dc.ColumnName)=false
选择dc;
targetTable.Columns.AddRange(dt2FilterQuery.ToArray());
var rowData=来自dt1.AsEnumerable()中的行1
在dt2.AsEnumerable()中加入行2
第1行的字段(“ID”)等于第2行的字段(“ID”)
选择row1.ItemArray.Concat(row2.ItemArray.Where(r2=>row1.ItemArray.Contains(r2==false)).ToArray();
foreach(rowData中的对象[]值)targetTable.Rows.Add(值);
返回目标;
}
}

在上面,我将“ID”硬编码为公共列。我需要动态生成/识别公共列。请帮帮我。

这个对我有用的东西怎么样:

private DataTable DataTableJoiner(DataTable dt1, DataTable dt2)
    {
        var commonColumns = dt1.Columns.OfType<DataColumn>().Intersect(dt2.Columns.OfType<DataColumn>(), new DataColumnComparer());

        var result = new DataTable();
        result.Columns.AddRange(
            dt1.Columns.OfType<DataColumn>()
            .Union(dt2.Columns.OfType<DataColumn>(), new DataColumnComparer())
            .Select(c => new DataColumn(c.Caption, c.DataType, c.Expression, c.ColumnMapping))
            .ToArray());

        var rowData = dt1.AsEnumerable().Join(
            dt2.AsEnumerable(),
            row => commonColumns.Select(col => row[col.Caption]).ToArray(),
            row => commonColumns.Select(col => row[col.Caption]).ToArray(),
            (row1, row2) => 
            {
                var row = result.NewRow();
                row.ItemArray = result.Columns.OfType<DataColumn>().Select(col => row1.Table.Columns.Contains(col.Caption) ? row1[col.Caption] : row2[col.Caption]).ToArray();
                return row;
            },
            new ObjectArrayComparer());

        foreach (var row in rowData)
            result.Rows.Add(row);

        return result;
    }
专用DataTable DataTableJoiner(DataTable dt1、DataTable dt2)
{
var commonColumns=dt1.Columns.OfType().Intersect(dt2.Columns.OfType(),new datacolumncomperator());
var result=新数据表();
result.Columns.AddRange(
dt1.Columns.OfType()
.Union(dt2.Columns.OfType(),新的DataColumnComparer())
.Select(c=>newdatacolumn(c.Caption、c.DataType、c.Expression、c.ColumnMapping))
.ToArray());
var rowData=dt1.AsEnumerable().Join(
dt2.AsEnumerable(),
行=>commonColumns.Select(列=>row[col.Caption]).ToArray(),
行=>commonColumns.Select(列=>row[col.Caption]).ToArray(),
(第1行,第2行)=>
{
var row=result.NewRow();
row.ItemArray=result.Columns.OfType().Select(col=>row1.Table.Columns.Contains(col.Caption)?row1[col.Caption]:row2[col.Caption]).ToArray();
返回行;
},
新的ObjectArrayComparer());
foreach(rowData中的变量行)
结果.行.添加(行);
返回结果;
}
要使其工作,您还需要声明这两个类:

private class DataColumnComparer : IEqualityComparer<DataColumn>
    {

        #region IEqualityComparer<DataColumn> Members

        public bool Equals(DataColumn x, DataColumn y)
        {
            return x.Caption == y.Caption;
        }

        public int GetHashCode(DataColumn obj)
        {
            return obj.Caption.GetHashCode();
        }

        #endregion
    }

    private class ObjectArrayComparer : IEqualityComparer<object[]>
    {
        #region IEqualityComparer<object[]> Members

        public bool Equals(object[] x, object[] y)
        {
            for (var i = 0; i < x.Length; i++)
            {
                if (!object.Equals(x[i], y[i]))
                    return false;
            }

            return true;
        }

        public int GetHashCode(object[] obj)
        {
            return obj.Sum(item => item.GetHashCode());
        }

        #endregion
    }
私有类DataColumnComparer:IEqualityComparer
{
#地区资格比较成员
公共布尔等于(数据列x、数据列y)
{
返回x.Caption==y.Caption;
}
public int GetHashCode(DataColumn obj)
{
返回obj.Caption.GetHashCode();
}
#端区
}
私有类ObjectArrayComparer:IEqualityComparer
{
#地区资格比较成员
公共布尔等于(对象[]x,对象[]y)
{
对于(变量i=0;iitem.GetHashCode());
}
#端区
}

我希望这有帮助

动态识别它们的规则是什么?如果我准备好了这样的东西,你可以简单地说基于列名。我无法停止思考(将“正则表达式”替换为“LINQ”)