你可以在这里使用我最近从头开始编写的这个扩展方法来解决另一个问题。它可以通过一个公共键合并多个表。如果没有指定键,它将只使用默认DataTable.Merge
方法:
public static DataTable MergeAll(this IList<DataTable> 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[] { Schema1, Schema2};
DataTable Schema3 = tables.MergeAll("ID");
编辑:如果您不需要新DataTable
的合并模式,您也可以使用Linq-To-DataSet
(现在是 VB.NET):
Dim schema3 = From r1 In schema1
Join r2 In schema2 On r1.Field(Of Int32)("ID") Equals r2.Field(Of Int32)("ID")
Select New With {
.ID = r1.Field(Of Int32)("ID"),
.Food = r1.Field(Of String)("Food"),
.Book = r1.Field(Of String)("Book"),
.Rice = r1.Field(Of String)("Rice"),
.Cave = r1.Field(Of String)("Cave"),
.Carpet = r2.Field(Of String)("Carpet"),
.Strings = r2.Field(Of String)("Strings"),
.Run = r2.Field(Of String)("Run")
}