加入2个包含许多列的DataTables
我有一个问题,想要加入2个同一列的表。 表1包含Name,LastName Columns和许多其他列,表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"... ... ... ...
所以我试着将这些行连在一起。 但是它说table1中的数组比表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);
你可以在这里使用这个方法,我最近从头开始写了另一个问题的 SO(所以它没有经过实际测试)。 它允许通过公共密钥合并多个表。 如果没有指定密钥,它将只使用默认的DataTable.Merge
方法:
public static DataTable MergeAll(this IList tables, String primaryKeyColumn) { if (!tables.Any()) throw new ArgumentException("Tables must not be empty", "tables"); if(primaryKeyColumn != null) foreach(DataTable t in tables) if(!t.Columns.Contains(primaryKeyColumn)) throw new ArgumentException("All tables must have the specified primarykey column " + primaryKeyColumn, "primaryKeyColumn"); if(tables.Count == 1) return tables[0]; DataTable table = new DataTable("TblUnion"); table.BeginLoadData(); // Turns off notifications, index maintenance, and constraints while loading data foreach (DataTable t in tables) { table.Merge(t); // same as table.Merge(t, false, MissingSchemaAction.Add); } table.EndLoadData(); if (primaryKeyColumn != null) { // since we might have no real primary keys defined, the rows now might have repeating fields // so now we're going to "join" these rows ... var pkGroups = table.AsEnumerable() .GroupBy(r => r[primaryKeyColumn]); var dupGroups = pkGroups.Where(g => g.Count() > 1); foreach (var grpDup in dupGroups) { // use first row and modify it DataRow firstRow = grpDup.First(); foreach (DataColumn c in table.Columns) { if (firstRow.IsNull(c)) { DataRow firstNotNullRow = grpDup.Skip(1).FirstOrDefault(r => !r.IsNull(c)); if (firstNotNullRow != null) firstRow[c] = firstNotNullRow[c]; } } // remove all but first row var rowsToRemove = grpDup.Skip(1); foreach(DataRow rowToRemove in rowsToRemove) table.Rows.Remove(rowToRemove); } } return table; }
你可以用这种方式调用它:
var tables = new[] { Table1, Table2 }; 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。 (您不需要知道其余列)以下是一些function:
- 结果DataTable不会有用于连接的重复列。 例如,如果您加入“名称”列,则最后只有一个“名称”列,而不是每个表中的一个副本。
- 如果重复列未在连接中使用,则第二个表中的重复列将通过在末尾附加“_2”来重命名。 它可以以其他方式运行,只需更改代码的那一部分。
- 支持多个Join列。 为此,创建了一个JoinKey类,使它们可以被LINQ比较。
-
这段代码是我在网上找到的代码和我的试错的混合物。 我是LINQ的新手,所以请随意批评〜
public class JoinKey { List