I am not using Entity Framework.
There are 2 Datatables, each with different no. of columns. There is one common column - ItemId
If it was Union, I would have used 'Merge', but don't know how to do a Union All for these 2 DataTables
public static void Main()
{
//First DataTable
DataTable dt1 = new DataTable();
dt1.Columns.Add("ItemId");
dt1.Columns.Add("Name");
dt1.Columns.Add("Color");
DataRow dr = dt1.NewRow();
dr["ItemId"] = "1";
dr["Name"] = "Name1";
dr["Color"] = "Color1";
dt1.Rows.Add(dr);
dr = dt1.NewRow();
dr["ItemId"] = "2";
dr["Name"] = "Name2";
dr["Color"] = "Color2";
dt1.Rows.Add(dr);
//Second DataTable
DataTable dt2 = new DataTable();
dt2.Columns.Add("ItemId");
dt2.Columns.Add("Name");
dt2.Columns.Add("Price");
DataRow dr2 = dt2.NewRow();
dr2["ItemId"] = "1";
dr2["Name"] = "Name1";
dr2["Price"] = "100";
dt2.Rows.Add(dr2);
dr2 = dt2.NewRow();
dr2["ItemId"] = "2";
dr2["Name"] = "Name3";
dr2["Price"] = "200";
dt2.Rows.Add(dr2);
}
Expected Output
ItemId Name Color Price
1 Name1 Color1
2 Name2 Color2
1 Name1 100
2 Name3 200
You can use DataTable.Merge()
If you have primary key in both the table then it will perform merge on primary key else it will directly append all the records.
In youe case make ItemID as primary key.
using System.Linq.Expressions;
......
var result1 = from row1 in dt1.AsEnumerable()
select new { Name = row1.Field<String>("Name"), Color = row1.Field<String>("Color"), Price = "" };
var result2 = from row1 in dt2.AsEnumerable()
select new { Name = row1.Field<String>("Name"), Color = "", Price = row1.Field<String>("Price") };
var res = result1.Concat(result2);
foreach (var item in res)
Console.WriteLine("{0} - {1} - {2}", item.Name, item.Color, item.Price);
Even though this question is years old, for anyone looking for another way to do this:
public static DataTable MergeTables(DataTable dt1, DataTable dt2)
{
DataTable dt3 = dt1.Clone();
foreach (DataColumn col in dt2.Columns)
{
string strColumnName = col.ColumnName;
int intColNum = 1;
while (dt3.Columns.Contains(strColumnName))
{
strColumnName = string.Format("{0}_{1}", col.ColumnName, ++intColNum);
}
dt3.Columns.Add(strColumnName, col.DataType);
}
var Mergered = dt1.AsEnumerable().Zip(dt2.AsEnumerable(), (r1, r2) => r1.ItemArray.Concat(r2.ItemArray).ToArray());
foreach (object[] rowFields in Mergered)
dt3.Rows.Add(rowFields);
return dt3;
}
Related
I have two DataTables and I want to select the rows from the first Table which are not present in second Table based on 2 columns(col1, col2) using linq
Please check below example
I tried example from this page
Compare two DataTables and select the rows that are not present in second table
from the example they are used only one column
Edit 1
I have tried
DataTable Table1 = new DataTable();
Table1.Columns.Add("col1", typeof(string));
Table1.Columns.Add("col2", typeof(string));
DataRow r1 = Table1.NewRow();
r1["col1"] = "A";
r1["col2"] = "A-1";
Table1.Rows.Add(r1);
DataRow r2 = Table1.NewRow();
r2["col1"] = "B";
r2["col2"] = "B-2";
Table1.Rows.Add(r2);
DataRow r3 = Table1.NewRow();
r3["col1"] = "C";
r3["col2"] = "C-3";
Table1.Rows.Add(r3);
DataRow r4 = Table1.NewRow();
r4["col1"] = "D";
r4["col2"] = "D-4";
Table1.Rows.Add(r4);
DataRow r5 = Table1.NewRow();
r5["col1"] = "E";
r5["col2"] = "E-5";
Table1.Rows.Add(r5);
DataTable Table2 = new DataTable();
Table2.Columns.Add("col1", typeof(string));
Table2.Columns.Add("col2", typeof(string));
DataRow r11 = Table2.NewRow();
r11["col1"] = "A";
r11["col2"] = "A-1";
Table2.Rows.Add(r11);
DataRow r22 = Table2.NewRow();
r22["col1"] = "B";
r22["col2"] = "B-2";
Table2.Rows.Add(r22);
DataRow r33 = Table2.NewRow();
r33["col1"] = "C";
r33["col2"] = "C-4";
Table2.Rows.Add(r33);
DataRow r44 = Table2.NewRow();
r44["col1"] = "D";
r44["col2"] = "DD";
Table2.Rows.Add(r44);
DataRow r55 = Table2.NewRow();
r55["col1"] = "E";
r55["col2"] = "EE";
Table2.Rows.Add(r55);
DataRow r66 = Table2.NewRow();
r66["col1"] = "F";
r66["col2"] = "FF";
Table2.Rows.Add(r66);
Example - 1
DataTable table3s = (from a in Table1.AsEnumerable()
where !Table2.AsEnumerable().Any(e => (e.Field<string>("col1") == a.Field<string>("col1"))
&& (e.Field<string>("col2") == a.Field<string>("col2")))
select a).CopyToDataTable();
Example - 2
DataTable TableC = Table1.AsEnumerable().Where(ra => !Table2.AsEnumerable()
.Any(rb => rb.Field<string>("col1") == ra.Field<string>("col1")
&& rb.Field<string>("col2") == ra.Field<string>("col2"))).CopyToDataTable();
Example 1 & 2 gives error when no matching rows
The source contains no DataRows
please give working example based on my sample code and suggest most efficient way because DataTable may contains large record like 10000 rows, 20000 rows and more
Or to have something with a proper outer join without an implicit loop using Any:
var res = from a in Table1
join b in Table2
on (a.col1, a.col2) equals (b.col1, b.col2)
into temp
from b in temp.DefaultIfEmpty(default)
where b.col2 == null
select a;
It just joins the two tables using a composite key and puts it into the temp table. Then it does an outer join (DefaultIfEmpty) and takes only those entries from Table1 where the join returned an empty result.
Assuming you have
class Table1
{
public string col1 { get; set; }
public string col2 { get; set; }
}
class Table2
{
public string col1 { get; set; }
public string col2 { get; set; }
}
and
List<Table1> table1s = new List<Table1>();
List<Table2> table2s = new List<Table2>();
the query is
var table3s = from table1 in table1s
where !table2s.Any(e => (e.col1 == table1.col1) && (e.col2 == table1.col2))
select table1;
Try this. Basically, this line of code selects every element from Table1 whose "col1" and "col2" values do not exist in Table2.
var results = Table1.AsEnumerable().Where(t1 => Table2.AsEnumerable().All(t2 => t2["col1"] !=
t1["col1"] || t2["col2"] != t1["col2"]));
I tried to resolve this using below logic. Please let me know if I missed something here?
static void LinkPerf()
{
string[] arr = { "A", "B", "C", "D", "E", "F", "G", "H", "I" };
DataTable table1 = new DataTable();
table1.Columns.Add("Id");
table1.Columns.Add("Col1");
table1.Columns.Add("Col2");
DataTable table2 = new DataTable();
table2.Columns.Add("Id");
table2.Columns.Add("Col1");
table2.Columns.Add("Col2");
DataTable ResultTable3 = new DataTable();
ResultTable3.Columns.Add("Id");
ResultTable3.Columns.Add("Col1");
ResultTable3.Columns.Add("Col2");
Random rand = new Random();
for (int i = 1; i <= 10000; i++)
{
DataRow row = table1.NewRow();
int index = rand.Next(arr.Length);
var colVal = arr[index];
//Table 1
row[0] = i.ToString();
row[1] = colVal;
row[2] = colVal + "-" + i.ToString();
table1.Rows.Add(row);
//Table 2
row = table2.NewRow();
row[0] = i.ToString();
row[1] = colVal;
row[2] = (i % 5 == 0) ? colVal + colVal + i.ToString() : colVal + "-" + i.ToString();
table2.Rows.Add(row);
}
Stopwatch watch = new Stopwatch();
watch.Start();
var result = table1.AsEnumerable()
.Where(ra => !table2.AsEnumerable()
.Any(rb => rb.Field<string>("Col1") == ra.Field<string>("Col1") && rb.Field<string>("Col2") == ra.Field<string>("Col2")));
if (result.Any())
{
foreach (var item in result)
{
ResultTable3.ImportRow(item);
}
}
watch.Stop();
var timeTaken = watch.Elapsed;
Console.WriteLine("Time taken: " + timeTaken.ToString(#"m\:ss\.fff"));
Console.ReadLine();
}
Let T1 and T2 are DataTables with following fields
T1(CustID, ColX, ColY)
T2(CustID, ColZ)
I need the joint table
TJ (CustID, ColX, ColY, ColZ)
How this can be done in C# code in a simple way? Thanks.
If you are allowed to use LINQ, take a look at the following example. It creates two DataTables with integer columns, fills them with some records, join them using LINQ query and outputs them to Console.
DataTable dt1 = new DataTable();
dt1.Columns.Add("CustID", typeof(int));
dt1.Columns.Add("ColX", typeof(int));
dt1.Columns.Add("ColY", typeof(int));
DataTable dt2 = new DataTable();
dt2.Columns.Add("CustID", typeof(int));
dt2.Columns.Add("ColZ", typeof(int));
for (int i = 1; i <= 5; i++)
{
DataRow row = dt1.NewRow();
row["CustID"] = i;
row["ColX"] = 10 + i;
row["ColY"] = 20 + i;
dt1.Rows.Add(row);
row = dt2.NewRow();
row["CustID"] = i;
row["ColZ"] = 30 + i;
dt2.Rows.Add(row);
}
var results = from table1 in dt1.AsEnumerable()
join table2 in dt2.AsEnumerable() on (int)table1["CustID"] equals (int)table2["CustID"]
select new
{
CustID = (int)table1["CustID"],
ColX = (int)table1["ColX"],
ColY = (int)table1["ColY"],
ColZ = (int)table2["ColZ"]
};
foreach (var item in results)
{
Console.WriteLine(String.Format("ID = {0}, ColX = {1}, ColY = {2}, ColZ = {3}", item.CustID, item.ColX, item.ColY, item.ColZ));
}
Console.ReadLine();
// Output:
// ID = 1, ColX = 11, ColY = 21, ColZ = 31
// ID = 2, ColX = 12, ColY = 22, ColZ = 32
// ID = 3, ColX = 13, ColY = 23, ColZ = 33
// ID = 4, ColX = 14, ColY = 24, ColZ = 34
// ID = 5, ColX = 15, ColY = 25, ColZ = 35
I wanted a function that would join tables without requiring you to define the columns using an anonymous type selector, but had a hard time finding any. I ended up having to make my own. Hopefully this will help anyone in the future who searches for this:
private DataTable JoinDataTables(DataTable t1, DataTable t2, params Func<DataRow, DataRow, bool>[] joinOn)
{
DataTable result = new DataTable();
foreach (DataColumn col in t1.Columns)
{
if (result.Columns[col.ColumnName] == null)
result.Columns.Add(col.ColumnName, col.DataType);
}
foreach (DataColumn col in t2.Columns)
{
if (result.Columns[col.ColumnName] == null)
result.Columns.Add(col.ColumnName, col.DataType);
}
foreach (DataRow row1 in t1.Rows)
{
var joinRows = t2.AsEnumerable().Where(row2 =>
{
foreach (var parameter in joinOn)
{
if (!parameter(row1, row2)) return false;
}
return true;
});
foreach (DataRow fromRow in joinRows)
{
DataRow insertRow = result.NewRow();
foreach (DataColumn col1 in t1.Columns)
{
insertRow[col1.ColumnName] = row1[col1.ColumnName];
}
foreach (DataColumn col2 in t2.Columns)
{
insertRow[col2.ColumnName] = fromRow[col2.ColumnName];
}
result.Rows.Add(insertRow);
}
}
return result;
}
An example of how you might use this:
var test = JoinDataTables(transactionInfo, transactionItems,
(row1, row2) =>
row1.Field<int>("TransactionID") == row2.Field<int>("TransactionID"));
One caveat: This is certainly not optimized, so be mindful when getting to row counts above 20k. If you know that one table will be larger than the other, try to put the smaller one first and the larger one second.
This is my code. Not perfect, but working good. I hope it helps somebody:
static System.Data.DataTable DtTbl (System.Data.DataTable[] dtToJoin)
{
System.Data.DataTable dtJoined = new System.Data.DataTable();
foreach (System.Data.DataColumn dc in dtToJoin[0].Columns)
dtJoined.Columns.Add(dc.ColumnName);
foreach (System.Data.DataTable dt in dtToJoin)
foreach (System.Data.DataRow dr1 in dt.Rows)
{
System.Data.DataRow dr = dtJoined.NewRow();
foreach (System.Data.DataColumn dc in dtToJoin[0].Columns)
dr[dc.ColumnName] = dr1[dc.ColumnName];
dtJoined.Rows.Add(dr);
}
return dtJoined;
}
this function will join 2 tables with a known join field, but this cannot allow 2 fields with the same name on both tables except the join field, a simple modification would be to save a dictionary with a counter and just add number to the same name filds.
public static DataTable JoinDataTable(DataTable dataTable1, DataTable dataTable2, string joinField)
{
var dt = new DataTable();
var joinTable = from t1 in dataTable1.AsEnumerable()
join t2 in dataTable2.AsEnumerable()
on t1[joinField] equals t2[joinField]
select new { t1, t2 };
foreach (DataColumn col in dataTable1.Columns)
dt.Columns.Add(col.ColumnName, typeof(string));
dt.Columns.Remove(joinField);
foreach (DataColumn col in dataTable2.Columns)
dt.Columns.Add(col.ColumnName, typeof(string));
foreach (var row in joinTable)
{
var newRow = dt.NewRow();
newRow.ItemArray = row.t1.ItemArray.Union(row.t2.ItemArray).ToArray();
dt.Rows.Add(newRow);
}
return dt;
}
I tried to do this in next way
public static DataTable JoinTwoTables(DataTable innerTable, DataTable outerTable)
{
DataTable resultTable = new DataTable();
var innerTableColumns = new List<string>();
foreach (DataColumn column in innerTable.Columns)
{
innerTableColumns.Add(column.ColumnName);
resultTable.Columns.Add(column.ColumnName);
}
var outerTableColumns = new List<string>();
foreach (DataColumn column in outerTable.Columns)
{
if (!innerTableColumns.Contains(column.ColumnName))
{
outerTableColumns.Add(column.ColumnName);
resultTable.Columns.Add(column.ColumnName);
}
}
for (int i = 0; i < innerTable.Rows.Count; i++)
{
var row = resultTable.NewRow();
innerTableColumns.ForEach(x =>
{
row[x] = innerTable.Rows[i][x];
});
outerTableColumns.ForEach(x =>
{
row[x] = outerTable.Rows[i][x];
});
resultTable.Rows.Add(row);
}
return resultTable;
}
Note that if you have a DataSet, you will need to steal the table from the Dataset with dataSet.Table[0]
I have this requirement that the user request one or more partnumbers.And i need to display all the result in one Data Set
Ex: Request SerialNumbers with
PartNumber Required Quantity
A 2
B 1
C 3
Code:
//Loop Request
foreach (DataRow a in request.Rows)
{
//select top(Quantity) SerialNumber,PartNumber where PartNumber=#PartNumber
var dt = new DataTable();
}
//1. PartNumber A
SerialNumber Partnumber
1 A
2 A
+
//2. PartNumber B
SerialNumber Partnumber
1 B
//3. PartNumber C
SerialNumber Partnumber
1 C
2 C
3 C
//Load to DataSet
And the result will be something like:
SerialNumber Partnumber
1 A
2 A
1 B
1 C
2 C
3 C
Thanks in Regards
I am not sure what two tables you wish to join here and on what key but regadless of that, the simplest way will be to use LINQ to Dataset. For example,
var query = from a in table1
join
b in table2
on
a.FkColumn = b.PKColumn select a,b;
Please check below logic:
DataTable myDataTable = new DataTable();
DataColumn PartNumber = new DataColumn("PartNumber");
DataColumn RequiredQuantity = new DataColumn("RequiredQuantity");
myDataTable.Columns.Add(PartNumber);
myDataTable.Columns.Add(RequiredQuantity);
DataRow dataRowPN1 = myDataTable.NewRow();
DataRow dataRowPN2 = myDataTable.NewRow();
DataRow dataRowPN3 = myDataTable.NewRow();
dataRowPN1["PartNumber"] = "A";
dataRowPN2["PartNumber"] = "B";
dataRowPN3["PartNumber"] = "C";
dataRowPN1["RequiredQuantity"] = "2";
dataRowPN2["RequiredQuantity"] = "1";
dataRowPN3["RequiredQuantity"] = "3";
myDataTable.Rows.Add(dataRowPN1);
myDataTable.Rows.Add(dataRowPN2);
myDataTable.Rows.Add(dataRowPN3);
int i = myDataTable.Rows.Count;
DataTable joinDataTable = new DataTable();
DataColumn SerialNumber = new DataColumn("SerialNumber");
DataColumn JoinPartNumber = new DataColumn("PartNumber");
joinDataTable.Columns.Add(SerialNumber);
joinDataTable.Columns.Add(JoinPartNumber);
foreach (DataRow dr in myDataTable.Rows)
{
for (int count = 1; count <= Convert.ToInt16(dr["RequiredQuantity"]); count++)
{
DataRow joindataRow = joinDataTable.NewRow();
joindataRow["SerialNumber"] = count.ToString().Trim();
joindataRow["PartNumber"] = dr["PartNumber"].ToString().Trim();
joinDataTable.Rows.Add(joindataRow);
}
}
Response.Write(joinDataTable.Rows.Count);
I have a datatable with 10 columns, but User can select the columns to be displayed so I need to create a generic code to display only the selected columns.
Current code:
string[] selectedColumns = new[] { };
DataTable columns = new DataView(table).ToTable(false, selectedColumns);
You could simply hide the columns in the datagridview (supposing you're using one)
dataGridView1.Columns["ColName"].Visible = False;
for every column that are not in selectedColumns
But if you really need to filter the dataset, I remember that you can do something like:
mydatatable.Columns.Remove("ColName");
in your datatable... or in a copy.
If you are going to show the columns in a datagridview, my option will be setting the ColumnMapping property of the datatable column like this
mydatatable.Columns["Colname"].ColumnMapping = MappingType.Hidden;
Unfortunatly I'm not at home now, so I can't test it, but as you can see, there are many options.
EDIT: In response to your request, you can deal with non selected columns like this:
for(int i = 0;i<dt.Columns.Count;i++)
{
if(!selectedColumns.Contains(dt.Columns[i].ColumnName))
{
dt.Columns[i].ColumnMapping = MappingType.Hidden;
}
}
public static void Main(string[] args)
{
DataTable act = new DataTable();
act.Columns.Add(new DataColumn("id", typeof(System.Int32)));
act.Columns.Add(new DataColumn("name"));
act.Columns.Add(new DataColumn("email"));
act.Columns.Add(new DataColumn("phone"));
DataRow dr = act.NewRow();
dr["id"] = 101;
dr["name"] = "Rama";
dr["email"] = "rama#mail.com";
dr["phone"] = "0000000001";
act.Rows.Add(dr);
dr = act.NewRow();
dr["id"] = 102;
dr["name"] = "Talla";
dr["email"] = "talla#mail.com";
dr["phone"] = "0000000002";
act.Rows.Add(dr);
dr = act.NewRow();
dr["id"] = 103;
dr["name"] = "Robert";
dr["email"] = "robert#mail.com";
dr["phone"] = "0000000003";
act.Rows.Add(dr);
dr = act.NewRow();
dr["id"] = 104;
dr["name"] = "Kevin";
dr["email"] = "kevin#mail.com";
dr["phone"] = "0000000004";
act.Rows.Add(dr);
dr = act.NewRow();
dr["id"] = 106;
dr["name"] = "TomChen";
dr["email"] = "tomchen#mail.com";
dr["phone"] = "0000000005";
act.Rows.Add(dr);
var lselColumns = new[] {"id", "name"};
var dt = act.DefaultView.ToTable(true, lselColumns);
foreach (DataRow drow in dt.Rows)
{
string drowData = string.Empty;
foreach (DataColumn r in drow.Table.Columns)
{
drowData += (drowData == string.Empty) ? drow[r] : "|" + drow[r];
}
Console.WriteLine(drowData);
}
Console.ReadLine();
}
Let T1 and T2 are DataTables with following fields
T1(CustID, ColX, ColY)
T2(CustID, ColZ)
I need the joint table
TJ (CustID, ColX, ColY, ColZ)
How this can be done in C# code in a simple way? Thanks.
If you are allowed to use LINQ, take a look at the following example. It creates two DataTables with integer columns, fills them with some records, join them using LINQ query and outputs them to Console.
DataTable dt1 = new DataTable();
dt1.Columns.Add("CustID", typeof(int));
dt1.Columns.Add("ColX", typeof(int));
dt1.Columns.Add("ColY", typeof(int));
DataTable dt2 = new DataTable();
dt2.Columns.Add("CustID", typeof(int));
dt2.Columns.Add("ColZ", typeof(int));
for (int i = 1; i <= 5; i++)
{
DataRow row = dt1.NewRow();
row["CustID"] = i;
row["ColX"] = 10 + i;
row["ColY"] = 20 + i;
dt1.Rows.Add(row);
row = dt2.NewRow();
row["CustID"] = i;
row["ColZ"] = 30 + i;
dt2.Rows.Add(row);
}
var results = from table1 in dt1.AsEnumerable()
join table2 in dt2.AsEnumerable() on (int)table1["CustID"] equals (int)table2["CustID"]
select new
{
CustID = (int)table1["CustID"],
ColX = (int)table1["ColX"],
ColY = (int)table1["ColY"],
ColZ = (int)table2["ColZ"]
};
foreach (var item in results)
{
Console.WriteLine(String.Format("ID = {0}, ColX = {1}, ColY = {2}, ColZ = {3}", item.CustID, item.ColX, item.ColY, item.ColZ));
}
Console.ReadLine();
// Output:
// ID = 1, ColX = 11, ColY = 21, ColZ = 31
// ID = 2, ColX = 12, ColY = 22, ColZ = 32
// ID = 3, ColX = 13, ColY = 23, ColZ = 33
// ID = 4, ColX = 14, ColY = 24, ColZ = 34
// ID = 5, ColX = 15, ColY = 25, ColZ = 35
I wanted a function that would join tables without requiring you to define the columns using an anonymous type selector, but had a hard time finding any. I ended up having to make my own. Hopefully this will help anyone in the future who searches for this:
private DataTable JoinDataTables(DataTable t1, DataTable t2, params Func<DataRow, DataRow, bool>[] joinOn)
{
DataTable result = new DataTable();
foreach (DataColumn col in t1.Columns)
{
if (result.Columns[col.ColumnName] == null)
result.Columns.Add(col.ColumnName, col.DataType);
}
foreach (DataColumn col in t2.Columns)
{
if (result.Columns[col.ColumnName] == null)
result.Columns.Add(col.ColumnName, col.DataType);
}
foreach (DataRow row1 in t1.Rows)
{
var joinRows = t2.AsEnumerable().Where(row2 =>
{
foreach (var parameter in joinOn)
{
if (!parameter(row1, row2)) return false;
}
return true;
});
foreach (DataRow fromRow in joinRows)
{
DataRow insertRow = result.NewRow();
foreach (DataColumn col1 in t1.Columns)
{
insertRow[col1.ColumnName] = row1[col1.ColumnName];
}
foreach (DataColumn col2 in t2.Columns)
{
insertRow[col2.ColumnName] = fromRow[col2.ColumnName];
}
result.Rows.Add(insertRow);
}
}
return result;
}
An example of how you might use this:
var test = JoinDataTables(transactionInfo, transactionItems,
(row1, row2) =>
row1.Field<int>("TransactionID") == row2.Field<int>("TransactionID"));
One caveat: This is certainly not optimized, so be mindful when getting to row counts above 20k. If you know that one table will be larger than the other, try to put the smaller one first and the larger one second.
This is my code. Not perfect, but working good. I hope it helps somebody:
static System.Data.DataTable DtTbl (System.Data.DataTable[] dtToJoin)
{
System.Data.DataTable dtJoined = new System.Data.DataTable();
foreach (System.Data.DataColumn dc in dtToJoin[0].Columns)
dtJoined.Columns.Add(dc.ColumnName);
foreach (System.Data.DataTable dt in dtToJoin)
foreach (System.Data.DataRow dr1 in dt.Rows)
{
System.Data.DataRow dr = dtJoined.NewRow();
foreach (System.Data.DataColumn dc in dtToJoin[0].Columns)
dr[dc.ColumnName] = dr1[dc.ColumnName];
dtJoined.Rows.Add(dr);
}
return dtJoined;
}
this function will join 2 tables with a known join field, but this cannot allow 2 fields with the same name on both tables except the join field, a simple modification would be to save a dictionary with a counter and just add number to the same name filds.
public static DataTable JoinDataTable(DataTable dataTable1, DataTable dataTable2, string joinField)
{
var dt = new DataTable();
var joinTable = from t1 in dataTable1.AsEnumerable()
join t2 in dataTable2.AsEnumerable()
on t1[joinField] equals t2[joinField]
select new { t1, t2 };
foreach (DataColumn col in dataTable1.Columns)
dt.Columns.Add(col.ColumnName, typeof(string));
dt.Columns.Remove(joinField);
foreach (DataColumn col in dataTable2.Columns)
dt.Columns.Add(col.ColumnName, typeof(string));
foreach (var row in joinTable)
{
var newRow = dt.NewRow();
newRow.ItemArray = row.t1.ItemArray.Union(row.t2.ItemArray).ToArray();
dt.Rows.Add(newRow);
}
return dt;
}
I tried to do this in next way
public static DataTable JoinTwoTables(DataTable innerTable, DataTable outerTable)
{
DataTable resultTable = new DataTable();
var innerTableColumns = new List<string>();
foreach (DataColumn column in innerTable.Columns)
{
innerTableColumns.Add(column.ColumnName);
resultTable.Columns.Add(column.ColumnName);
}
var outerTableColumns = new List<string>();
foreach (DataColumn column in outerTable.Columns)
{
if (!innerTableColumns.Contains(column.ColumnName))
{
outerTableColumns.Add(column.ColumnName);
resultTable.Columns.Add(column.ColumnName);
}
}
for (int i = 0; i < innerTable.Rows.Count; i++)
{
var row = resultTable.NewRow();
innerTableColumns.ForEach(x =>
{
row[x] = innerTable.Rows[i][x];
});
outerTableColumns.ForEach(x =>
{
row[x] = outerTable.Rows[i][x];
});
resultTable.Rows.Add(row);
}
return resultTable;
}
Note that if you have a DataSet, you will need to steal the table from the Dataset with dataSet.Table[0]