Merge two datatables? - c#

I want to merge two data table in which column "ID" as primary key in both table.
Note: Both table has two column as "ID, Name" & "ID, name" where Name & name is case sensitive.
Table: 1
Table: 2
Expected Merged Table Result:
Code:
public MainWindow()
{
InitializeComponent();
// Table 1
DataTable table1 = new DataTable();
table1.Columns.Add("ID", typeof(int));
table1.Columns.Add("Name", typeof(String));
table1.PrimaryKey = new DataColumn[] { table1.Columns["ID"] };
table1.Rows.Add(1, "A");
table1.Rows.Add(4, "D");
table1.Rows.Add(5, "E");
// Table 2
DataTable table2 = new DataTable();
table2.Columns.Add("ID", typeof(int));
table2.Columns.Add("name", typeof(String));
table2.PrimaryKey = new DataColumn[] { table2.Columns["ID"] };
table2.Rows.Add(1, "A");
table2.Rows.Add(2, "B");
table2.Rows.Add(3, "C");
table2.Rows.Add(5, "E");
table1.Merge(table2);
}
Please help me to achieve this expected result.

You could temporarily change the name of the second column and still use Merge:
const string OriginalName = "name";
const string TemporaryName = "temp";
table2.Columns[OriginalName].ColumnName = TemporaryName;
table1.Merge(table2);
table1.Columns[TemporaryName].ColumnName = OriginalName;
table2.Columns[TemporaryName].ColumnName = OriginalName;

Use this:
DataTable dtResult = new DataTable();
dtResult.Columns.Add("ID", typeof(int));
dtResult.Columns.Add("Name", typeof(string));
dtResult.Columns.Add("name", typeof(string));
var result = from dataRows1 in table1.AsEnumerable()
join dataRows2 in table2.AsEnumerable()
on dataRows1.Field<int>("ID") equals dataRows2.Field<int>("ID")
into rows
from row in rows.DefaultIfEmpty()
select dtResult.LoadDataRow(new object[]
{
dataRows1.Field<int>("ID"),
dataRows1.Field<string>("Name"),
dataRows2.Field<string>("name")
}, false);

Related

How to link a ComboBox to a Column of DataGrid Control in WinForms? - C#

Here is a part of my code:
// building a dataset
DataSet ds = new DataSet("Stud_Prog");
DataTable student = new DataTable("Student");
DataColumn stud_ID = student.Columns.Add("Student_ID", typeof(int));
DataColumn stud_name = student.Columns.Add("Name", typeof(string));
DataColumn stud_surname = student.Columns.Add("Surname", typeof(string));
DataColumn stud_grade = student.Columns.Add("Grade", typeof(string));
stud_ID.AutoIncrement = true;
stud_ID.AutoIncrementSeed = 1;
stud_ID.Unique = true;
student.PrimaryKey = new DataColumn[] { stud_ID };
DataTable grade = new DataTable("Grade");
DataColumn grad_ID = grade.Columns.Add("Grade_ID", typeof(int));
DataColumn grad_gradeType = grade.Columns.Add("Grade Type", typeof(string));
grade.PrimaryKey = new DataColumn[] { grad_ID };
grade.Rows.Add(1, "A");
// ...
student.Rows.Add(null, "AAA", "AAA");
// ...
ds.Tables.Add(student);
ds.Tables.Add(grade);
ds.Relations.Add("StudentGradeRelation", ds.Tables[1].Columns[0], ds.Tables[0].Columns[3]);
DataGrid studentGrid = new DataGrid();
DataGrid gradeGrid = new DataGrid();
// adding to the form
// ...
studentGrid.DataSource = ds.Tables[0];
gradeGrid.DataSource = ds.Tables[1];
// ...
I need Grade column cells of Student table to look like ComboBoxes that would offer me to choose one of the grade types contained inside the Grade table.

how to add two datatables dt1=2 column ,dt2=3 column, into one datatable dt3=5 column

how to add two datatables?
(dt1=name,phone_number)
and
(dt2=address,cityname)
Result:
(dt3=name,phone_number,address,cityname)
Ruben, you will need some primary key in order to combine both tables unless you are 100% sure that both data tables have the same number of rows and they will always be stored in the correct order.
There is a similar question answered and the link is: Combining n DataTables into a Single DataTable
Here goes the content of the provided link:
"The table has repeating primary keys after the Merge because no primary-key was defined. So either specify the PK or try this method here which i've written from scratch(so it's not really tested):
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;
}
You can call it in this way:
var tables = new[] { tblA, tblB, tblC };
DataTable TblUnion = tables.MergeAll("c1");
Used this sample data:
var tblA = new DataTable();
tblA.Columns.Add("c1", typeof(int));
tblA.Columns.Add("c2", typeof(int));
tblA.Columns.Add("c3", typeof(string));
tblA.Columns.Add("c4", typeof(char));
var tblB = new DataTable();
tblB.Columns.Add("c1", typeof(int));
tblB.Columns.Add("c5", typeof(int));
tblB.Columns.Add("c6", typeof(string));
tblB.Columns.Add("c7", typeof(char));
var tblC = new DataTable();
tblC.Columns.Add("c1", typeof(int));
tblC.Columns.Add("c8", typeof(int));
tblC.Columns.Add("c9", typeof(string));
tblC.Columns.Add("c10", typeof(char));
tblA.Rows.Add(1, 8500, "abc", 'A');
tblA.Rows.Add(2, 950, "cde", 'B');
tblA.Rows.Add(3, 150, "efg", 'C');
tblA.Rows.Add(4, 850, "ghi", 'D');
tblA.Rows.Add(5, 50, "ijk", 'E');
tblB.Rows.Add(1, 7500, "klm", 'F');
tblB.Rows.Add(2, 900, "mno", 'G');
tblB.Rows.Add(3, 150, "opq", 'H');
tblB.Rows.Add(4, 850, "qrs", 'I');
tblB.Rows.Add(5, 50, "stu", 'J');
tblC.Rows.Add(1, 7500, "uvw", 'K');
tblC.Rows.Add(2, 900, "wxy", 'L');
tblC.Rows.Add(3, 150, "yza", 'M');
tblC.Rows.Add(4, 850, "ABC", 'N');
tblC.Rows.Add(5, 50, "CDE", 'O');
After DataTable.Merge in MergeAll:
After some modifications to join the rows in MergeAll:
Update
Since this question arose in one of the comments, if the only relation between two tables is the index of a DataRow in the table and you want to merge both tables according to the index:
public static DataTable MergeTablesByIndex(DataTable t1, DataTable t2)
{
if (t1 == null || t2 == null) throw new ArgumentNullException("t1 or t2", "Both tables must not be null");
DataTable t3 = t1.Clone(); // first add columns from table1
foreach (DataColumn col in t2.Columns)
{
string newColumnName = col.ColumnName;
int colNum = 1;
while (t3.Columns.Contains(newColumnName))
{
newColumnName = string.Format("{0}_{1}", col.ColumnName, ++colNum);
}
t3.Columns.Add(newColumnName, col.DataType);
}
var mergedRows = t1.AsEnumerable().Zip(t2.AsEnumerable(),
(r1, r2) => r1.ItemArray.Concat(r2.ItemArray).ToArray());
foreach (object[] rowFields in mergedRows)
t3.Rows.Add(rowFields);
return t3;
}
Sample:
var dt1 = new DataTable();
dt1.Columns.Add("ID", typeof(int));
dt1.Columns.Add("Name", typeof(string));
dt1.Rows.Add(1, "Jon");
var dt2 = new DataTable();
dt2.Columns.Add("Country", typeof(string));
dt2.Rows.Add("US");
var dtMerged = MergeTablesByIndex(dt1, dt2);
The result table contains three columns ID,Name,Country and a single row: 1 Jon US"
Source: Combining n DataTables into a Single DataTable
Last Access: 04-August-2016
First you can filter right column in to separate data datable
DataTable filterDatatable1= new DataTable();
DataTable filterDatatable2= new DataTable();
DataTable filterDatatable1= OriginaDatatable1.DefaultView.ToTable(false, "ColumnName1", "ColimnName2");
DataTable filterDatatable1= OriginaDatatable1.DefaultView.ToTable(false, "ColumnName1", "ColimnName2", "ColimnName3");
Then you can use merge function
DataTable dtAll = new DataTable();
dtAll.Merge(filterDatatable1);
dtAll.Merge(filterDatatable2);

GridView from 2 DataTables

I have a dataset contains 2 datatables with a relation between them,
in the first table i have an ID (primary key) and MainAreaName and in the second table I have the ID from the first table with 2 other columns
the question is: how to view the MainAreaName from the first table with the other 2 columns from the second table in a gridview
DataSet MyDB = new DataSet("MyDB");
DataTable MainArea = new DataTable("MainArea");
DataTable NameNumber = new DataTable("NameNumber");
DataColumn Col01 = new DataColumn("ID", typeof(int));
Col01.AutoIncrement = true;
Col01.AutoIncrementSeed = 1;
Col01.AutoIncrementStep = 1;
DataColumn Col02 = new DataColumn("MainAreaName", typeof(string));
MainArea.Columns.Add(Col01);
MainArea.Columns.Add(Col02);
MainArea.PrimaryKey =
new DataColumn[] { MainArea.Columns["ID"] };
DataRow MyRow = MainArea.NewRow();
MyRow["MainAreaName"] = "Area1";
MainArea.Rows.Add(MyRow);
MyRow = MainArea.NewRow();
MyRow["MainAreaName"] = "Area2";
MainArea.Rows.Add(MyRow);
DataColumn Col11 = new DataColumn("MainAreaID", typeof(int));
DataColumn Col12 = new DataColumn("Name", typeof(string));
DataColumn Col13 = new DataColumn("Number", typeof(int));
DataColumn Col14 = new DataColumn("Comment", typeof(string));
NameNumber.Columns.Add(Col11);
NameNumber.Columns.Add(Col12);
NameNumber.Columns.Add(Col13);
NameNumber.Columns.Add(Col14);
NameNumber.PrimaryKey =
new DataColumn[] {
NameNumber.Columns["MainAreaID"], NameNumber.Columns["Number"] };
NameNumber.Rows.Add(1, "Test1", 67);
NameNumber.Rows.Add(1, "Test2", 87);
NameNumber.Rows.Add(2, "Test3", 77);
NameNumber.Rows.Add(2, "Test4", 88);
MyDB.Tables.Add(MainArea);
MyDB.Tables.Add(NameNumber);
MyDB.Relations.Add(
MyDB.Tables["MainArea"].Columns["ID"],
MyDB.Tables["NameNumber"].Columns["MainAreaID"]);
I tried to use the following code
DataRelation DR = new DataRelation("MainAreaRelation", MyDB.Tables["MainArea"].Columns["ID"], MyDB.Tables["NameNumber"].Columns["MainAreaID"]);
dataGridView1.DataSource = MyDB.Relations["MainAreaRelation"].ParentTable;
//or
dataGridView1.DataSource = MyDB.Relations["MainAreaRelation"].ParentTable;
but didn't work,
anyone can help please?

Datatable.Merge doesn't work

DataTable Table = CreateTableStucture();
DataTable Table_2 = Table.Clone();
Table.Rows.Add(0, "A", "B");
Table_2.Rows.Add(0, DBNull.Value, DBNull.Value, "C");
Table.Merge(Table_2);
Why after executing this code object:Table has row with values just from Table_2 and it's not merged as it should. These tables must have the same structure because my program requires it.
EDIT 1.
DataTable Table = new DataTable("table");
DataColumn KeyCol = new DataColumn("Key", typeof(int));
DataColumn Col1 = new DataColumn("col1", typeof(string));
DataColumn Col2 = new DataColumn("col2", typeof(string));
DataColumn Col3 = new DataColumn("col3", typeof(string));
DataColumn Col4 = new DataColumn("col4", typeof(string));
DataColumn Col5 = new DataColumn("col5", typeof(string));
Table.Columns.Add(KeyCol);
Table.Columns.Add(Col1);
Table.Columns.Add(Col2);
Table.Columns.Add(Col3);
Table.Columns.Add(Col4);
Table.Columns.Add(Col5);
Table.Constraints.Add("keyCon", KeyCol, true);
DataTable Table_2 = new DataTable();
Table_2 = Table.Clone();
Table.Rows.Add(0, "A", "B");
Table_2.Rows.Add(0, DBNull.Value, DBNull.Value, "C");
Table.Merge(Table_2);
Even that I create them this way it doesn't work.
The problem is you are having a primary key conflict.
DataColumn KeyCol = new DataColumn("Key", typeof(int));
//...
Table.Constraints.Add("keyCon", KeyCol, true);
//...
Table.Rows.Add(0, "A", "B");
Table_2.Rows.Add(0, DBNull.Value, DBNull.Value, "C");
You have a primary key of 0 for both rows, change the 2nd row to 1 and it should work.
You need to use Table.Copy() instead of Data.Clone()
From MSDN:
DataTable.Copy Copies both the structure and data for this DataTable.
DataTable.Clone Clones the structure of the DataTable, including all DataTable schemas
and constraints.

how to insert data to dataset

i have this making table:
DataTable WorkTbl()
{
DataTable Work= new DataTable("Work"); //Table Name
DataColumn MAC = new DataColumn("MAC", typeof(string));
DataColumn ID_OLD = new DataColumn("ID_OLD", typeof(string));
Work.Columns.Add(MAC);
Work.Columns.Add(ID_OLD);
return Work;
}
how to insert data to this table and how to convert this table to Dataset ?
thanks in advance
From MSDN:
DataRow workRow = workTable.NewRow();
You then can manipulate the newly added row using an index or the column name, as shown in the following example.
workRow["CustLName"] = "Smith";
workRow[1] = "Smith";
DataSet customerOrders = new DataSet("CustomerOrders");
DataTable ordersTable = customerOrders.Tables.Add("Orders");
DataColumn pkOrderID =
ordersTable.Columns.Add("OrderID", typeof(Int32));
ordersTable.Columns.Add("OrderQuantity", typeof(Int32));
ordersTable.Columns.Add("CompanyName", typeof(string));
ordersTable.PrimaryKey = new DataColumn[] { pkOrderID };

Categories

Resources