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
Related
I want to copy the content from one datatable to another without copying or cloning the data structure. what is the best way to do this?
I need to do it this way because I am given a datatable from a SQL server stored procedure and I cannot amend the given read only table. so I need recreate it without copying all the underlying structure.
I hope that makes sense.
Regards
Amarino
If you want to copy dataTable you have two options first one is copy or clone.
The second option is using foreach or for loop to copy you can get any columns from dataTable
int columnsize = dt.Columns.Count;
foreach (DataRow X in dt.Rows)
{
for (int i = 0; i < columnsize; i++)
{
// int bir = Convert.ToInt32(X[i]);
// you can set here your need dataTable
}
}
// then here new dataTable you can assing to any datagridview.DataSource = newDataTable
but in the second case you should know ahead what data will come in which place to look this you can get any cell and assing it new DataTable
here is my using code
DataTable dh1 = new DataTable("data1");
dh1.Columns.Add("specification_name", typeof(string));
dh1.Columns.Add("summalar", typeof(string));
dh1.Columns.Add("address", typeof(string));
dh1.Columns.Add("id1", typeof(int));
dh1.Columns.Add("client_id", typeof(int));
dh1.Columns.Add("stack_id", typeof(int));
foreach (DataRow dd in dt.Rows)
{
DataTable temp = new DataTable("temp");
DataRow ttt = dh1.NewRow();
for (int j = 0; j < col; j++)
{
ttt[0] = dd[1];
ttt[1] = dd[2];
ttt[2] = dd[3];
ttt[3] = dd[4];
ttt[4] = dd[5];
ttt[5] = dd[6];
break;
}
dh1.Rows.Add(ttt);
}
I was looking to do something like this: The below solution works for me.
DataTable lDT2 = someMethod(); //populated with data from SomeMethod()
DataTable lDT3 = new DataTable();
lDT3.Columns.Add("Name", typeof(string));
lDT3.Columns.Add("Name2", typeof(string));
foreach (DataColumn col in lDT2.Columns) {
lDT3.Columns.Add(col.ColumnName, col.DataType);
}
foreach (DataRow dr in lDT2.Rows) {
DataRow lDT3dr = lDT3.NewRow();
for (int i = 0; i < lDT2.Columns.Count; i++) {
if (i == 0) { lDT3dr[i] = "some info"; }
if (i == 1) { lDT3dr[i] = "more info"; }
lDT3dr[i+2] = dr[i];
}
lDT3.Rows.Add(lDT3dr);
}
If I understand correctly you want to copy the data but ignore the schema. You can do this by gathering data set from the source table then iterate through each row and insert it into the destination table.
This is a simple way to copy data from one table to another without any worry of keys or constraints. You will need to make sure your destination table can accept the data (it must be of the correct type or you must cast it to something acceptable).
Another option is to use DefaultView.ToTable(). This also allows you to pull DISTINCT values. If you want all columns
var myNewTable = ExistingDataTable.DefaultView().ToTable();
If you wanted to limit for some criteria
var dv = ExistingDataTable.DefaultView();
dv.Filter = "SomeColumn = 'SomeValue'";
var myFilteredTable = dv.ToTable();
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"]
};
My Datatable 1 (dtOutput) Format (termid,faultid,faultdesc,faulttime,devicetype)
My Datatable 2 (dtOpenEvent) Format (termid,faultid)
I want to retrieve those values which are present in Datatable 2 but not in Datatable 1...based on two columns (termid,faultid) no table have primary keys.
I Searched on net and find code which return diff between two data table...
Now how can i retrieve column values from it ? either in another data table or in string variable
Code :-
DataTable dtOpenEvent;
dtOpenEvent = Generix.getOpenEvents(ref Connection);
DataTable dtOutput;
dtOutput = Generix.getFeedData(ref Connection);
var matched = from table1 in dtOpenEvent.AsEnumerable()
join table2 in dtOutput.AsEnumerable() on table1.Field<string>("ATM") equals table2.Field<string>("termid")
where table1.Field<int>("Event") == table2.Field<int>("faultid")
select table1;
var missing = from table1 in dtOpenEvent.AsEnumerable()
where !matched.Contains(table1)
select table1;
you can remove all of the columns in dt1 and then do except.
like this:
var diff =dt2.AsEnumerable().Except(dt1.AsEnumerable(), DataRowComparer.Default);
full example:
DataTable dt1 = new DataTable();
DataTable dt2 = new DataTable();
dt1.Columns.Add("termid", typeof(Int32));
dt1.Columns.Add("faultid", typeof(Int32));
dt1.Columns.Add("faultdesc");
dt2.Columns.Add("termid", typeof(Int32));
dt2.Columns.Add("faultid", typeof(Int32));
dt1.Rows.Add(1,2,"desc");
dt1.Rows.Add(3, 4, "desc");
dt1.Rows.Add(5, 6, "desc");
dt2.Rows.Add(1, 2);
dt2.Rows.Add(3, 4);
dt2.Rows.Add(7, 8);
dt1.Columns.Remove("faultdesc");
var diff =dt2.AsEnumerable().Except(dt1.AsEnumerable(), DataRowComparer.Default);
foreach (var row in diff)
{
Console.WriteLine(row["termid"] + " " + row["faultid"]); //prints 7 8
}
or instead of removing columns you can select them through linq or dataview like this:
var view = new DataView(dt1);
DataTable dt3 = view.ToTable(true, "termid", "faultid");
modified example:
DataTable dt1 = new DataTable();
DataTable dt2 = new DataTable();
dt1.Columns.Add("termid", typeof(Int32));
dt1.Columns.Add("faultid", typeof(Int32));
dt1.Columns.Add("faultdesc");
dt2.Columns.Add("termid", typeof(Int32));
dt2.Columns.Add("faultid", typeof(Int32));
dt1.Rows.Add(1,2,"desc");
dt1.Rows.Add(3, 4, "desc");
dt1.Rows.Add(5, 6, "desc");
dt2.Rows.Add(1, 2);
dt2.Rows.Add(3, 4);
dt2.Rows.Add(7, 8);
var view = new DataView(dt1);
DataTable dt3 = view.ToTable(true, "termid", "faultid");
var diff =dt2.AsEnumerable().Except(dt3.AsEnumerable(), DataRowComparer.Default);
foreach (var row in diff)
{
Console.WriteLine(row["termid"] + " " + row["faultid"]);
}
As you said : I want to retrieve those values which are present in Datatable 2
but not in Datatable 1...based on two columns `(termid,faultid)`
Translation according to the context of question : You have two tables dtOutput and dtOpenEvent. You want to get values of dtOutput in a third table such that no row of third table has same value with first two cells of any row of dtOpenEvent. Then here it is
DataTable dt3 = new DataTable();
dt3.Columns.Add("termid");
dt3.Columns.Add("faultid");
int nr = 0;
for (int i = 0; i < dtOutput.Rows.Count; i++)
{
bool found = false;
for (int j = 0; j < dtOpenEvent.Rows.Count; j++)
{
if (dtOutput.Rows[i][0] == dtOpenEvent.Rows[j][0]
&& dtOutput.Rows[i][1] == dtOpenEvent.Rows[j][1])
{
found = true;
break;
}
}
if (!found)
{
dt3.Rows.Add(dt3.NewRow());
dt3.Rows[nr][0] = dtOutput.Rows[i][0];
dt3.Rows[nr][1] = dtOutput.Rows[i][1];
nr++;
}
}
I have a datatable with 20 columns. But i don't need all the columns for the current processing except 5. So i did the below to remove the columns
List<string> clmnames = new List<string>() { "clm6","clm7"..."clm20" };
foreach (string dcName in clmnames)
{
TestAndRemoveColumn(dcName, ds.Tables["TestTable"]);
}
private void TestAndRemoveColumn(string dcName,DataTable datatable)
{
DataColumnCollection dcCollection = datatable.Columns;
if (dcCollection.Contains(dcName))
{
dcCollection.Remove(dcName);
}
}
Instead of looping through the 15 times is there any other way to achieve using easily ?
try this
List<string> listtoRemove = new List<string> { "CLM6", "CLM7", "CLM20" };
for (int i = dt.Columns.Count - 1; i >= 0; i--)
{
DataColumn dc = dt.Columns[i];
if (listtoRemove.Contains(dc.ColumnName.ToUpper()))
{
dt.Columns.Remove(dc);
}
}
In some scenarios may be preferable to clone DataTable and specify columns to copy.
DataView view = new DataView(table);
DataTable table2 = view.ToTable(false, "clm6", "clm7", ...);
Problem seems to be in your code, you get all the comlumns from the datatable then remove the columns but you have not again assign the columns to that datatable
first you get columns
DataColumnCollection dcCollection = datatable.Columns; // get cols
if (dcCollection.Contains(dcName))
{
dcCollection.Remove(dcName); /// remove columns
// but you have not updated you datatable columns.
here should be something like this
datatable.Columns = dcCollection; /// i don't know this will work or not check it
}
Try this
DataTable dt;
dt.Columns.Remove("columnName");
dt.Columns.RemoveAt(columnIndex);
you can use them as
private void TestAndRemoveColumn(string dcName,DataTable datatable)
{
DataTable dt = datatable;
dt.Columns.Remove("dcName");
}
Alternatively you can select only the required columns(Only 5 in your case) like this.
DataTable dt = new DataTable();
dt.Columns.Add("ID");
dt.Columns.Add("Value");
dt.Rows.Add("1", "One");
dt.Rows.Add("2", "Two");
string[] arr= new string[1];
arr[0] = "Value";//add the required columns to the array
//return only the required columns.
DataTable dt2 = dt.DefaultView.ToTable(false, arr);
You could join the columns you want remove with the available columns:
var keepColNames = new List<String>(){ "clm5" };
var allColumns = tbl.Columns.Cast<DataColumn>();
var allColNames = allColumns.Select(c => c.ColumnName);
var removeColNames = allColNames.Except(keepColNames);
var colsToRemove = from r in removeColNames
join c in allColumns on r equals c.ColumnName
select c;
while (colsToRemove.Any())
tbl.Columns.Remove(colsToRemove.First());
If you know that you only have few remaining columns, you could add the column(s):
var colsToAdd = (from keepCol in keepColNames
join col in tbl.Columns.Cast<DataColumn>()
on keepCol equals col.ColumnName
select col).ToList();
tbl.Columns.Clear();
foreach (var colToAdd in colsToAdd)
tbl.Columns.Add(colToAdd);
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.