Jak "złączyć" 2 lub więcej DataTables w języku C#?Jak "złączyć" 2 lub więcej DataTables w C#?
Obie tabela ma tę samą strukturę.
Czy jest jakaś funkcja wbudowana lub czy powinniśmy wykonywać ręcznie?
Jak "złączyć" 2 lub więcej DataTables w języku C#?Jak "złączyć" 2 lub więcej DataTables w C#?
Obie tabela ma tę samą strukturę.
Czy jest jakaś funkcja wbudowana lub czy powinniśmy wykonywać ręcznie?
Szukacie najprawdopodobniej metody DataTable.Merge.
Przykład:
private static void DemonstrateMergeTable()
{
DataTable table1 = new DataTable("Items");
// Add columns
DataColumn idColumn = new DataColumn("id", typeof(System.Int32));
DataColumn itemColumn = new DataColumn("item", typeof(System.Int32));
table1.Columns.Add(idColumn);
table1.Columns.Add(itemColumn);
// Set the primary key column.
table1.PrimaryKey = new DataColumn[] { idColumn };
// Add RowChanged event handler for the table.
table1.RowChanged += new
System.Data.DataRowChangeEventHandler(Row_Changed);
// Add ten rows.
DataRow row;
for (int i = 0; i <= 9; i++)
{
row = table1.NewRow();
row["id"] = i;
row["item"] = i;
table1.Rows.Add(row);
}
// Accept changes.
table1.AcceptChanges();
PrintValues(table1, "Original values");
// Create a second DataTable identical to the first.
DataTable table2 = table1.Clone();
// Add column to the second column, so that the
// schemas no longer match.
table2.Columns.Add("newColumn", typeof(System.String));
// Add three rows. Note that the id column can't be the
// same as existing rows in the original table.
row = table2.NewRow();
row["id"] = 14;
row["item"] = 774;
row["newColumn"] = "new column 1";
table2.Rows.Add(row);
row = table2.NewRow();
row["id"] = 12;
row["item"] = 555;
row["newColumn"] = "new column 2";
table2.Rows.Add(row);
row = table2.NewRow();
row["id"] = 13;
row["item"] = 665;
row["newColumn"] = "new column 3";
table2.Rows.Add(row);
// Merge table2 into the table1.
Console.WriteLine("Merging");
table1.Merge(table2, false, MissingSchemaAction.Add);
PrintValues(table1, "Merged With table1, schema added");
}
private static void Row_Changed(object sender,
DataRowChangeEventArgs e)
{
Console.WriteLine("Row changed {0}\t{1}", e.Action,
e.Row.ItemArray[0]);
}
private static void PrintValues(DataTable table, string label)
{
// Display the values in the supplied DataTable:
Console.WriteLine(label);
foreach (DataRow row in table.Rows)
{
foreach (DataColumn col in table.Columns)
{
Console.Write("\t " + row[col].ToString());
}
Console.WriteLine();
}
}
można spróbować to:
public static DataTable Union (DataTable First, DataTable Second)
{
//Result table
DataTable table = new DataTable("Union");
//Build new columns
DataColumn[] newcolumns = new DataColumn[First.Columns.Count];
for(int i=0; i < First.Columns.Count; i++)
{
newcolumns[i] = new DataColumn(
First.Columns[i].ColumnName, First.Columns[i].DataType);
}
table.Columns.AddRange(newcolumns);
table.BeginLoadData();
foreach(DataRow row in First.Rows)
{
table.LoadDataRow(row.ItemArray,true);
}
foreach(DataRow row in Second.Rows)
{
table.LoadDataRow(row.ItemArray,true);
}
table.EndLoadData();
return table;
}
Od here (nie testowane).
Można użyć Concat z Linq do zbiorów danych (pobierz darmowy rozdział LINQ w działaniu) do nich dołączyć, a następnie .AsDataTable do tworzenia tabeli (zakładając, że rzeczywiście chcą je jako DataTable)
nie używam LINQ ... – Dhana
LINQ jest jak jQuery świata dostępu do technologii .NET, jest odpowiedzią na wszystko. – TheTXI
@LazyBoy: Wkrótce będziesz (poważnie, rozdział książki przechodzi przez zestaw System.Data.DataSetExtensions i zalety, które oferuje rozszerzenie DataSets, aby zaoferować jeszcze więcej mocy niż DataSets już oferują (i z tą zakręconą mocą. ..)). @TheTXI: Jeśli nie można tego zrobić przez zraszanie w niektórych PS i niektórych LINQ, o co chodzi: D –
natknęliśmy się na to pytanie, a Ruben Bartelink dał świetną odpowiedź, ale bez kodu. Musiałem więc sprawdzić to gdzie indziej, co pokonało punkt StackOverflow. Teraz, kiedy jest rok 2010, inne udzielone odpowiedzi nie są tak realistyczne. Dla odniesienia, oto kod demonstrujący metodę rozszerzenia CopyToDataTable(). Jest w VB tak aby nie kraść kredyt od Ruben jeśli chce powrócić do przeszłości i umieścić pełniejszą odpowiedź :)
Public Function GetSchema(ByVal dbNames As IEnumerable(Of String)) As DataTable
Dim schemaTables As New List(Of DataTable)()
For Each dbName As String In dbNames
Dim cnnStr = GetConnectionString(dbName)
Dim cnn As New SqlConnection(cnnStr)
cnn.Open()
Dim dt = cnn.GetSchema("Columns")
cnn.Close()
schemaTables.Add(dt)
Next
Dim dtResult As DataTable = Nothing
For Each dt As DataTable In schemaTables
If dtResult Is Nothing Then
dtResult = dt
Else
dt.AsEnumerable().CopyToDataTable(dtResult, LoadOption.PreserveChanges)
End If
Next
Return dtResult
End Function
Spróbuj przy użyciu LINQ do DataSet, należy dodać odwołanie do System.Data. DataSetExtensions.dll, inne podejście, alternatywa dla metody DataTable.Merge).
static void Main(string[] args)
{
DoUnion();
}
private static void DoUnion()
{
DataTable table1 = GetProducts();
DataTable table2 = NewProducts();
var tbUnion = table1.AsEnumerable()
.Union(table2.AsEnumerable());
DataTable unionTable = table1.Clone();
foreach (DataRow fruit in tbUnion)
{
var fruitValue = fruit.Field<string>(0);
Console.WriteLine("{0}->{1}", fruit.Table, fruitValue);
DataRow row = unionTable.NewRow();
row.SetField<string>(0, fruitValue);
unionTable.Rows.Add(row);
}
}
private static DataTable NewProducts()
{
DataTable table = new DataTable("CitricusTable");
DataColumn col = new DataColumn("product", typeof(string));
table.Columns.Add(col);
string[] citricusFruits = { "Orange", "Grapefruit", "Lemon", "Lime", "Tangerine" };
foreach (string fruit in citricusFruits)
{
DataRow row = table.NewRow();
row.SetField<string>(col, fruit);
table.Rows.Add(row);
}
return table;
}
private static DataTable GetProducts()
{
DataTable table = new DataTable("MultipleFruitsTable");
DataColumn col = new DataColumn("product", typeof(string));
table.Columns.Add(col);
string[] multipleFruits = { "Breadfruit", "Custardfruit", "Jackfruit", "Osage-orange", "Pineapple" };
foreach (string fruit in multipleFruits)
{
DataRow row = table.NewRow();
row.SetField<string>(col, fruit);
table.Rows.Add(row);
}
return table;
}
Antonio
Może chce też wziąć pod uwagę przypadek, gdy oba DataTables mają pasujący rekord (te same wartości dla wszystkich kolumn) –