C# 将2个数据表与多个列连接起来
我有一个问题,想连接两个具有相同列的表。表1有Name、LastName列和许多其他列,表2有Name、Comment和许多其他列。我想用Name列连接它们,结果应该是Name、LastName、Comment和其他列。我尝试使用外部左Linq,但不知道如何编写select new,因为我不知道还有多少列 我的表1: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 ... ... .
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");
以下是我的一点贡献。此部分代码可用于连接指定列名上的任意两个数据表。(您不需要知道其余各列)以下是一些功能:
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
以下是我的一点贡献。此部分代码可用于连接指定列名上的任意两个数据表。(您不需要知道其余各列)以下是一些功能:
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;
}