Join Datatables from a loop and merge in one Dataset - c#

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);

Related

Linq - How to use 2 columns in where clause

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();
}

How to perform a Union All on 2 DataTables

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;
}

How to get each value from a particular mysql table by using datatable without using a for or foreach loop in c#?

I need to get each value from mysql table by using DataTable without using a loop. Here I have two DataTables, I want to increment dtfilmsngtemp and need to get values, i.e if dtsnglyric have id=2, Then I need to have get id=2 in dtfilmsngtemp, So in general I need to get he same 'id's' from two DataTables. First of all row id is 1 in dtsnglyric and dtfilmsngtemp, But dtsnglyric is incremented to 2, According to my requirement dtfilmsngtemp is also need to become 2. How it is possible?
DataTable dtsnglyric = GetAllsnglyrctmp();
DataTable dtfilmsngtemp = GetAllfilmsngtemp();
foreach (DataRow drow1 in dtsnglyric.Rows)
{
string lyrsct = drow1["lyricist"].ToString();
string sngrs = drow1["singers"].ToString();
foreach (DataRow drow in dtfilmsngtemp.Rows)
{
string lid = drow["lyric_id"].ToString();
string fid = drow["film_id"].ToString();
}
}
Try this
protected void Page_Load(object sender, EventArgs e)
{
// Check
if (!IsPostBack)
{
// Variable
DataTable dt1 = new DataTable();
DataTable dt2 = new DataTable();
DataRow[] dr1 = null;
DataRow[] dr2 = null;
string value1 = string.Empty;
string value2 = string.Empty;
dt1.Columns.Add("A");
dt1.Columns.Add("B");
dt2.Columns.Add("A");
dt2.Columns.Add("B");
// Add to DataTable
for (int i = 0; i < 10; i++)
{
dt1.Rows.Add(i.ToString(), (i + 1).ToString());
dt2.Rows.Add(i.ToString(), (i + 2).ToString());
}
// Find By Select Example i want to take dt1 Column A = 2 and dt2 Column A = 9
dr1 = dt1.Select("A=2"); // Select statement >>> Column = Value
dr2 = dt2.Select("A=9");
// Check & Get B Value
if (dr1 != null && dr1.Length == 1) value1 = dr1[0]["B"] + "";
if (dr2 != null && dr2.Length == 1) value2 = dr2[0]["B"] + "";
Response.Write(value1 + ":" + value2);
}
}
I think you need an inner join operation. Can't you do it in the SQL query? DataTable doesn't support that, but you can do it with LINQ. However, note that it will take O(n^2) time and shouldn't be used for big tables:
var results = from table1 in dtsnglyric.AsEnumerable()
join table2 in dtfilmsngtemp.AsEnumerable() on (int)table1["lyricist"] equals (int)table2["lyric_id"]
select new
{
lyricist= (int)table1["lyricist"],
lyric_id= (int)table2["lyric_id"],
film_id= (int)table2["film_id"],
singers = (int)table1["singers"]
};

How to merge two datatables in c# (without any common identifier)?8

I am trying to merge two data table dt and dt4. I want to merge 2 data tables, having different schemas, and no common identifier together. Becuase the first data table dt contains some values.I get dt count on x. Based on that count I have to fetch some value table and stored in dt4. if if dt contains 3 row value then x=3 and dt4 contains 3 values. After these process I have to merge dt and dt4 and displayed as one table.
While using the given below code getting one error. The error is : "'column' argument cannot be null." Help me to find a proper soluion. Thank you.
Code:
protected void ddlCircle_SelectedIndexChanged(object sender, EventArgs e)
{
ShadingAnalysisDataSetTableAdapters.tbl_CadEngineersTeamTableAdapter cd;
cd = new ShadingAnalysisDataSetTableAdapters.tbl_CadEngineersTeamTableAdapter();
DataTable dt = new DataTable();
dt = cd.GetAvailableData(ddlCircle.SelectedValue); // Getting details of unassigned site
int x, y;
DataTable dt3 = new DataTable();
dt3 = cd.GetTeam();
y = dt3.Rows.Count;
x = dt.Rows.Count; // counting the unassinged sites
DataTable dt2 = new DataTable();
dt2 = cd.GetAssignTeam(x); //Getting team based on count
string[] arr = new string[dt2.Rows.Count];
int i = 0;
foreach (DataRow r in dt2.Rows)
{
arr[i] = r["Team"].ToString(); // assigning available team to array
i++;
}
string[] strArr = new string[x+1]; // another array to copy arr values.
i = 0; int j = 0;
while (j <= x)
{
strArr[j]= arr[i] ; // copying the arr[] values into strArr[] based on count.
i++;
j++;
if (i == y)
{
i = 0;
}
}
DataTable dt4 = new DataTable();
dt4.Columns.Add("Team");
foreach (string s in strArr)
{
dt4.Rows.Add(s); // Converting string array strArr[] to data table dt4
}
dt.Merge(dt4); // error poppup here. Error : 'column' argument cannot be null.
GridView2.DataSource = dt;
GridView2.DataBind();
}
dt contain
State District SiteID SiteName
----- -------- ------ --------
Sate1 District1 1001 A
Sate2 District2 1002 B
Sate3 District3 1003 C
dt4 contain
Team
-----
Team1
Team2
Team3
I need a final output as:
State District SiteID SiteName Team
----- -------- ------ -------- -----
Sate1 District1 1001 A Team1
Sate2 District2 1002 B Team2
Sate3 District3 1003 C Team3
Do you have relationship. If you have primary key ID in First Table and you can add ID column in Second Table
See here MSDN Article Merge Datatables
If you add a relationship between the 2 datatables, like a common identifier - you would be able to extract the common columns between datatables automatically using Linq.
Something like the following;
var commonColumns = dt1.Columns.OfType<DataColumn>().Intersect(dt2.Columns.OfType<DataColumn>(), new DataColumnComparer());
DataTable result = new DataTable();
dt1.PrimaryKey = commonColumns.ToArray();
result.Merge(dt1, false, MissingSchemaAction.AddWithKey);
result.Merge(dt2, false, MissingSchemaAction.AddWithKey);
Have a look at a previous question about this Full outer join, on 2 data tables, with a list of columns
The given code is working perfectly. Thank you for all valuable comments.
Code :
protected void ddlCircle_SelectedIndexChanged(object sender, EventArgs e)
{
ShadingAnalysisDataSetTableAdapters.tbl_CadEngineersTeamTableAdapter cd;
cd = new ShadingAnalysisDataSetTableAdapters.tbl_CadEngineersTeamTableAdapter();
DataTable dt = new DataTable();
dt = cd.GetAvailableData(ddlCircle.SelectedValue); // Getting details of unassigned site
int x, y;
DataTable dt3 = new DataTable();
dt3 = cd.GetTeam();
y = dt3.Rows.Count;
x = dt.Rows.Count; // counting the unassinged sites
DataTable dt2 = new DataTable();
dt2 = cd.GetAssignTeam(x); //Getting team based on count
string[] arr = new string[dt2.Rows.Count];
int i = 0;
foreach (DataRow r in dt2.Rows)
{
arr[i] = r["Team"].ToString(); // assigning available team to array
i++;
}
string[] strArr = new string[x+1]; // another array to copy arr values.
i = 0; int j = 0;
while (j <= x)
{
strArr[j]= arr[i] ; // copying the arr[] values into strArr[] based on count.
i++;
j++;
if (i == y)
{
i = 0;
}
}
DataTable dt4 = new DataTable();
dt4.Columns.Add("Team");
foreach (string s in strArr)
{
dt4.Rows.Add(s); // Converting string array strArr[] to data table dt4
}
//Adding new data table for merging two table details
DataTable dt7 = new DataTable();
//create columns and copy data from dt:
dt7 = dt.Copy();
foreach (DataColumn column in dt4.Columns)
dt7.Columns.Add(column.ColumnName, typeof(string));
//copy data from dt4:
foreach (DataRow row in dt4.Rows)
{
dt7.Rows[dt4.Rows.IndexOf(row)][5] = row[0];
}
GridView3.DataSource = dt7;
GridView3.DataBind();
}
You don't have relationship with table dt and table dt4.
Problem::You are facing this error because you dont have any relation between these two data tables.
I think you better start by adding relationship first. If you have primary key ID in dt and you can add ID column in dt4 with the relevant ID.
So first create a column in both tables which is common and then on basis of that relationship
you can use DataTable.Merge method directly

DataTable Join or Merge

I have 3 Data tables populated with a dataset and table adapters/ binding sources and i need to run a Join query or find another way to get specific data. (the dataset contains each table listed)
Tables:
Product Table:
Prod_ID Name
1 tv
2 couch
Consumer Table:
Con_Id Name City
----------------------
1 Gray New York
2 Joe Chicago
3 Steve Madison
Transactions Table
Tran_Id Con_ID Prod_ID Price
-------------------------------------
1 2 1 900
2 1 2 300
Given a product name i need to populate a table with each distinct city and how much that product has sold for in that city (add all prices for that product to any consumer in a given city)
I am really stumped and cant find a way. (i have tried alot)
Please help and thank you!
Nudiers approach so far:
DataRelation relation = null;
DataColumn table1Column = null;
DataColumn table2Column = null;
DataColumn table3Column = null;
table1Column = tlobergeDataSet.Tb_Product.Columns[0];
table2Column = tlobergeDataSet.Tb_Transactions.Columns[3];
table3Column = tlobergeDataSet.Tb_Consumer.Columns[0];
relation = new DataRelation("relation", table1Column, table2Column);
tlobergeDataSet.Relations.Add(relation);
public DataTable MergeTables(DataTable dtFirst, DataTable dtSecond, string CommonColumn)
{
DataTable dtResults = dtFirst.Clone();
int count = 0;
for (int i = 0; i < dtSecond.Columns.Count; i++)
{
if (!dtFirst.Columns.Contains(dtSecond.Columns[i].ColumnName))
{
dtResults.Columns.Add(dtSecond.Columns[i].ColumnName, dtSecond.Columns[i].DataType);
count++;
}
}
DataColumn[] columns = new DataColumn[count];
int j = 0;
for (int i = 0; i < dtSecond.Columns.Count; i++)
{
if (!dtFirst.Columns.Contains(dtSecond.Columns[i].ColumnName))
{
columns[j++] = new DataColumn(dtSecond.Columns[i].ColumnName, dtSecond.Columns[i].DataType);
}
}
dtResults.BeginLoadData();
foreach (DataRow dr in dtFirst.Rows)
{
dtResults.Rows.Add(dr.ItemArray);
}
foreach (DataRow dr in dtSecond.Rows)
{
foreach (DataRow dr1 in dtResults.Rows)
{
if (dr1[CommonColumn].ToString().Equals(dr[CommonColumn].ToString()))
{
foreach (DataColumn c in columns)
{
dr1[c.ColumnName] = dr[c.ColumnName];
}
}
}
}
dtResults.EndLoadData();
return dtResults;
}
try with this.
DataRelation relation = null;
DataColumn table1Column = null;
DataColumn table2Column = null;
//retrieve column
table1Column = ds.Tables("Table1").Columns(0);
table2Column = ds.Tables("table2").Columns(0);
//relating tables
relation = new DataRelation("relation", table1Column, table2Column);
//assign relation to dataset
ds.Relations.Add(relation);
You can only relate two tables in a DataRelation object and to access the data from
the dataset is straightforward because the data has been already related.
DataRelation relation = null;
DataColumn table1Column = null;
DataColumn table2Column = null;
DataColumn table3Column = null;
table1Column = tlobergeDataSet.Tb_Product.Columns[0];
table2Column = tlobergeDataSet.Tb_Transactions.Columns[2];
table2Column1 = tlobergeDataSet.Tb_Transactions.Columns[1];
table3Column = tlobergeDataSet.Tb_Consumer.Columns[0];
relation = new DataRelation("relation", table1Column, table2Column);
tlobergeDataSet.Relations.Add(relation);
relation = new DataRelation("relation1", table3Column , table2Column1);
tlobergeDataSet.Relations.Add(relation);
In LINQ, you can join the tables to find the data you want with syntax like so:
from a in keyTable
join b in anotherTable on a.Key equals b.Key
join c in aThirdTable on a.Key equals c.Key
select new
{
// Anonymous Object Properties using identifier a, b, and c to get data
};
You should be able to take that snippet and generate a linq query that will generate an anonymous object containing the specific data representation that you need.

Categories

Resources