Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将2个数据表与多个列连接起来_C#_Linq_Join_Concat - Fatal编程技术网

C# 将2个数据表与多个列连接起来

C# 将2个数据表与多个列连接起来,c#,linq,join,concat,C#,Linq,Join,Concat,我有一个问题,想连接两个具有相同列的表。表1有Name、LastName列和许多其他列,表2有Name、Comment和许多其他列。我想用Name列连接它们,结果应该是Name、LastName、Comment和其他列。我尝试使用外部左Linq,但不知道如何编写select new,因为我不知道还有多少列 我的表1: Name1 LastName ... Niki Row ... Hube Slang ... Koke Mi ... ... .

我有一个问题,想连接两个具有相同列的表。表1有Name、LastName列和许多其他列,表2有Name、Comment和许多其他列。我想用Name列连接它们,结果应该是Name、LastName、Comment和其他列。我尝试使用外部左Linq,但不知道如何编写select new,因为我不知道还有多少列

我的表1:

Name1   LastName ...
Niki   Row      ...
Hube   Slang    ...
Koke   Mi       ... 
...    ...      ...
...    ...      ...
表2:

Name  Comment   ...
Koke   "Hello"  ...
Niki   "Hi"     ...
结果应该是:

Name   LastName   Comment ...
Niki    Row        "Hi"   ...
Hube    Sland             ...
Koke    Mi         "Hello"...
...     ...               ...
所以我试着把这两排排成一排。但是它说表1中的数组比表2中的数组长。还有别的办法加入吗

        foreach (DataRow tbE in Table1.Rows)
        {
            foreach (DataRow opT in Table2.Rows)
            {
                if (tbE["Name"].ToString() == opT["Name"].ToString())
                {
                    var row = Result.NewRow();
                    row.ItemArray = tbE.ItemArray
                                       .Concat(opT.ItemArray).ToArray();

                    Result.Rows.Add(row);
                }
                else
                    Result.ImportRow(tbE);

            }
        } 
        Result.Columns.Remove(Name); 

您可以在这里使用我最近从无到有编写的这个方法(所以它没有真正经过测试)。它允许通过一个公共键合并多个表。如果未指定任何键,则只使用默认方法:

编辑:以下是调试器的屏幕截图和示例数据:

所以它起作用了:)

此处的样本数据和测试:

var Table1 = new DataTable();
var Table2 = new DataTable();
Table1.Columns.Add("Name");
Table1.Columns.Add("LastName");

Table2.Columns.Add("Name");
Table2.Columns.Add("Comment");

Table1.Rows.Add("Niki", "Row");
Table1.Rows.Add("Hube", "Slang");
Table1.Rows.Add("Koke", "Mi");

Table2.Rows.Add("Koke", "Hello");
Table2.Rows.Add("Niki", "Hi");

var tables = new DataTable[] { Table1, Table2 };
DataTable merged = tables.MergeAll("Name");

您可以在这里使用我最近从无到有编写的这个方法(所以它没有真正经过测试)。它允许通过一个公共键合并多个表。如果未指定任何键,则只使用默认方法:

编辑:以下是调试器的屏幕截图和示例数据:

所以它起作用了:)

此处的样本数据和测试:

var Table1 = new DataTable();
var Table2 = new DataTable();
Table1.Columns.Add("Name");
Table1.Columns.Add("LastName");

Table2.Columns.Add("Name");
Table2.Columns.Add("Comment");

Table1.Rows.Add("Niki", "Row");
Table1.Rows.Add("Hube", "Slang");
Table1.Rows.Add("Koke", "Mi");

Table2.Rows.Add("Koke", "Hello");
Table2.Rows.Add("Niki", "Hi");

var tables = new DataTable[] { Table1, Table2 };
DataTable merged = tables.MergeAll("Name");

以下是我的一点贡献。此部分代码可用于连接指定列名上的任意两个数据表。(您不需要知道其余各列)以下是一些功能:

  • 对于联接中使用的列,结果DataTable将不会有重复的列。e、 g.如果您在“Name”列上加入,则最后只有一个“Name”列,而不是每个表的一个副本
  • 如果在联接中未使用重复列,则第二个表中的重复列将通过在末尾添加“_2”来重命名。它可以以其他方式运行,只需更改代码的这一部分
  • 支持多个联接列。为此,将创建一个JoinKey类,以便LINQ对它们进行比较
  • 这段代码混合了我在网上找到的代码和我的尝试和错误。我是LINQ的新手,所以请随意评论~

    public class JoinKey
    {
        List<object> objects { get; set; }
    
        public JoinKey(List<object> objects)
        {
            this.objects = objects;
        }
    
        public override bool Equals(object obj)
        {
            if (obj == null || obj.GetType() != typeof(JoinKey))
                return false;
            return objects.SequenceEqual(((JoinKey)obj).objects);
        }
    
        public override int GetHashCode()
        {
            int hash = 0;
            foreach (var foo in objects)
            {
                hash = hash * 31 + foo.GetHashCode();
            }
            return hash;
        }
    }
    
    public enum JoinType
    {
        Inner = 0,
        Left = 1
    }
    
        //Joins two tables and spits out the joined new DataTable. Tables are joined on onCol column names
        //If the right table has column name clashes with the left column, the column names will be appended "_2" and added to joined table
        public static DataTable Join(DataTable left, DataTable right, JoinType joinType, params string[] onCol)
        {
            Func<DataRow, object> getKey = (row) =>
            {
                return new JoinKey(onCol.Select(str => row[str]).ToList());
            };
            var dt = new DataTable(left.TableName);
            var colNumbersToRemove = new List<int>();
            //Populate the columns
            foreach (DataColumn col in left.Columns)
            {
                if (dt.Columns[col.ColumnName] == null)
                    dt.Columns.Add(new DataColumn(col.ColumnName, col.DataType, col.Expression, col.ColumnMapping));
            }
            for (int colIdx = 0; colIdx < right.Columns.Count; ++colIdx)
            {
                var col = right.Columns[colIdx];
                //if this is joined column, it will be removed.
                if (onCol.Contains(col.ColumnName))
                {
                    colNumbersToRemove.Add(colIdx);
                }
                else
                {
                    //if this is duplicate column, it will be renamed.
                    if (dt.Columns[col.ColumnName] != null)
                    {
                        col.ColumnName += "_2";
                    }
                    dt.Columns.Add(new DataColumn(col.ColumnName, col.DataType, col.Expression, col.ColumnMapping));
                }
            }
    
            if (joinType == JoinType.Left)
            {
                var res = from l in left.AsEnumerable()
                          join r in right.AsEnumerable()
                          on getKey(l) equals getKey(r) into temp
                          from r in temp.DefaultIfEmpty()
                          select l.ItemArray.Concat(((r == null) ? (right.NewRow().ItemArray) : r.ItemArray).Minus(colNumbersToRemove)).ToArray();
                foreach (object[] values in res)
                    dt.Rows.Add(values);
            }
            else
            {
                //Inner Join
                var res = from l in left.AsEnumerable()
                          join r in right.AsEnumerable()
                          on getKey(l) equals getKey(r) into temp
                          from r in temp
                          select l.ItemArray.Concat(((r == null) ? (right.NewRow().ItemArray) : r.ItemArray).Minus(colNumbersToRemove)).ToArray();
                foreach (object[] values in res)
                    dt.Rows.Add(values);
            }
            return dt;
        }
    
    公共类JoinKey
    {
    列出对象{get;set;}
    公钥(列出对象)
    {
    this.objects=对象;
    }
    公共覆盖布尔等于(对象对象对象)
    {
    if(obj==null | | obj.GetType()!=typeof(JoinKey))
    返回false;
    返回objects.SequenceEqual((JoinKey)obj.objects);
    }
    公共覆盖int GetHashCode()
    {
    int hash=0;
    foreach(对象中的变量foo)
    {
    hash=hash*31+foo.GetHashCode();
    }
    返回散列;
    }
    }
    公共枚举类型
    {
    内部=0,
    左=1
    }
    //联接两个表并输出联接的新数据表。表在onCol列名上联接
    //如果右表的列名与左表的列名冲突,则列名将被追加“_2”并添加到联接表中
    公共静态DataTable联接(DataTable left、DataTable right、JoinType JoinType、params string[]Oncl)
    {
    Func getKey=(行)=>
    {
    返回新的JoinKey(onCol.Select(str=>row[str]).ToList());
    };
    var dt=新的数据表(左表名);
    var colNumbersToRemove=新列表();
    //填充列
    foreach(左.Columns中的数据列col)
    {
    if(dt.Columns[col.ColumnName]==null)
    添加(新数据列(列名称、列数据类型、列表达式、列映射));
    }
    对于(int colIdx=0;colIdx

  • 以下是我的一点贡献。此部分代码可用于连接指定列名上的任意两个数据表。(您不需要知道其余各列)以下是一些功能:

  • 对于联接中使用的列,结果DataTable将不会有重复的列。e、 g.如果您在“Name”列上加入,则最后只有一个“Name”列,而不是每个表的一个副本
  • 如果联接中没有使用重复列,则ap将重命名第二个表中的重复列
    public class JoinKey
    {
        List<object> objects { get; set; }
    
        public JoinKey(List<object> objects)
        {
            this.objects = objects;
        }
    
        public override bool Equals(object obj)
        {
            if (obj == null || obj.GetType() != typeof(JoinKey))
                return false;
            return objects.SequenceEqual(((JoinKey)obj).objects);
        }
    
        public override int GetHashCode()
        {
            int hash = 0;
            foreach (var foo in objects)
            {
                hash = hash * 31 + foo.GetHashCode();
            }
            return hash;
        }
    }
    
    public enum JoinType
    {
        Inner = 0,
        Left = 1
    }
    
        //Joins two tables and spits out the joined new DataTable. Tables are joined on onCol column names
        //If the right table has column name clashes with the left column, the column names will be appended "_2" and added to joined table
        public static DataTable Join(DataTable left, DataTable right, JoinType joinType, params string[] onCol)
        {
            Func<DataRow, object> getKey = (row) =>
            {
                return new JoinKey(onCol.Select(str => row[str]).ToList());
            };
            var dt = new DataTable(left.TableName);
            var colNumbersToRemove = new List<int>();
            //Populate the columns
            foreach (DataColumn col in left.Columns)
            {
                if (dt.Columns[col.ColumnName] == null)
                    dt.Columns.Add(new DataColumn(col.ColumnName, col.DataType, col.Expression, col.ColumnMapping));
            }
            for (int colIdx = 0; colIdx < right.Columns.Count; ++colIdx)
            {
                var col = right.Columns[colIdx];
                //if this is joined column, it will be removed.
                if (onCol.Contains(col.ColumnName))
                {
                    colNumbersToRemove.Add(colIdx);
                }
                else
                {
                    //if this is duplicate column, it will be renamed.
                    if (dt.Columns[col.ColumnName] != null)
                    {
                        col.ColumnName += "_2";
                    }
                    dt.Columns.Add(new DataColumn(col.ColumnName, col.DataType, col.Expression, col.ColumnMapping));
                }
            }
    
            if (joinType == JoinType.Left)
            {
                var res = from l in left.AsEnumerable()
                          join r in right.AsEnumerable()
                          on getKey(l) equals getKey(r) into temp
                          from r in temp.DefaultIfEmpty()
                          select l.ItemArray.Concat(((r == null) ? (right.NewRow().ItemArray) : r.ItemArray).Minus(colNumbersToRemove)).ToArray();
                foreach (object[] values in res)
                    dt.Rows.Add(values);
            }
            else
            {
                //Inner Join
                var res = from l in left.AsEnumerable()
                          join r in right.AsEnumerable()
                          on getKey(l) equals getKey(r) into temp
                          from r in temp
                          select l.ItemArray.Concat(((r == null) ? (right.NewRow().ItemArray) : r.ItemArray).Minus(colNumbersToRemove)).ToArray();
                foreach (object[] values in res)
                    dt.Rows.Add(values);
            }
            return dt;
        }