How to: Join 2 DataTables with same Row Count - c#

I've got these two DataTables:
Table1:
Columns->"Timestamp1,Result1"
Row[0]->"someTime,someResult"
Table2:
Columns->"Timestamp2,Result2"
Row[0]->"someotherTime", "someotherResult"
Now I want to get a result table or string[] or string like this:
Table Result:
Columns->"Timestamp1,Result1,Timestamp2,Result2"
Row[0]->"someTime,someResult,someotherTime,someotherResult"
Is there a simple Way of doing this? Even if the tables got more rows then one?
I've allready got some solution for joining the Columns to a string:
StringBuilder sb = new StringBuilder();
foreach (DataTable dt in data_set.Tables)
{
sb.Append(string.Join(",", dt.Columns.Cast<DataColumn>().Select(x => x.ColumnName).ToArray()));
sb.Append(",");
}
Output with the example tables will be a String like this >> "Timestamp1, Result1,Timestamp2,Result2"
So using linq could be possible, but unfortunately I dont get it...
Could someone help me please?
Best regards
Edit:
Both tables should have the same count of rows! Merge will not work, because it will just not join one rows from two different tables into a new single one. Merge will just output 2 Rows in the new table.

from your both tables, get the below result table :
var resultTable = from t1 in dataTable1.AsEnumerable()
join t2 in dataTable2.AsEnumerable()
on t1.Field<int>("ID") equals t2.Field<int>("ID")
select new { t1, t2 };
then after apply your logic on resultTable for getting your result

Ok I solved it on my own... this code looks for every column in dt2 and if it's not existing in dt1, it will start the copy process.
foreach (DataColumn dc in data_table2.Columns)
{
//Only new Columns
if (!data_table1.Columns.Contains(dc.ColumnName))
{
//Add all new Columns to dt1
data_table1.Columns.Add(dc.ColumnName, dc.DataType);
//interate over all rows
foreach (DataRow dr in data_table2.Rows)
{
//Copy single value from dt2 in dt1
data_table1.Rows[dr.Table.Rows.IndexOf(dr)][data_table1.Columns.IndexOf(dc.ColumnName)] = dr[dc.ColumnName];
}
}
}

Related

Compare Two Data tables values and add to new data table if different for add, update and delete

How can I add similar values from two DataTables A and B (same columns/rows may be different) to a new DataTable C for CRUD operations containing the similar values of first 2 Data Tables? Please advise.
Look like you don't put your effort to resolve it. Any there it is you can do to resolve your problem.
DataTable table1 = new DataTable();
table1.Columns.Add("MyId");
table1.Columns.Add("Column1");
table1.Columns.Add("Column2");
DataTable table2 = new DataTable();
table2.Columns.Add("Column3");
table2.Columns.Add("MyId");
table2.Columns.Add("Column4");
DataTable table3 = new DataTable();
table3.Columns.Add("Column5");
table3.Columns.Add("MyId");
table3.Columns.Add("Column6");
foreach (DataRow drtable1 in table1.Rows)
{
foreach (DataRow drtable2 in table2.Rows)
{
if (Convert.ToString(drtable1["MyId"]) == Convert.ToString(drtable2["MyId"]))
{
table3.Rows.Add(drtable1["MyId"], drtable1["Column1"], drtable1["Column2"]);
}
}
}

Add data in datatable row by row [duplicate]

Here i want to find the Matched Records From Two data tables. the code is
public DataTable textfiltering(DataTable dtfff, DataTable dtff)
{
DataTable ds = (DataTable)Session["maintxt"];
DataTable dts = (DataTable)Session["sectxt"];
dtfff = ds;
dtff = dts;
DataTable dtMerged = (from a in dtfff.AsEnumerable()
join b in dtff.AsEnumerable()
on a["contacts"].ToString() equals b["contacts"].ToString()
into g
where g.Count()>0
select a).CopyToDataTable();
return dtMerged;
}
it gives "The source contains no DataRows" when Data tables does not contain Matched Records...
How to rectify it..pls give your suggistions
Two ways:
either check if it contains rows with Enumerable.Any before you call CopyToDataTable
use dtfff.Clone to create an empty DataTable with the same schema as the source table and use a loop to fill it from the LINQ query.
First approach:
var rows = from a in dtfff.AsEnumerable()
join b in dtff.AsEnumerable()
on a["contacts"].ToString() equals b["contacts"].ToString()
into g
where g.Count() > 0
select a;
DataTable merged;
if (rows.Any())
merged = rows.CopyToDataTable();
else
merged = dtfff.Clone();
return merged;
Second approach:
DataTable merged = dtfff.Clone();
foreach (DataRow sourceRow in rows)
{
merged.ImportRow(sourceRow); // or add all fields manually
}
return merged;
I prefer the second approach since it only needs to execute the query once.

How to fix "The source contains no DataRows"?

Here i want to find the Matched Records From Two data tables. the code is
public DataTable textfiltering(DataTable dtfff, DataTable dtff)
{
DataTable ds = (DataTable)Session["maintxt"];
DataTable dts = (DataTable)Session["sectxt"];
dtfff = ds;
dtff = dts;
DataTable dtMerged = (from a in dtfff.AsEnumerable()
join b in dtff.AsEnumerable()
on a["contacts"].ToString() equals b["contacts"].ToString()
into g
where g.Count()>0
select a).CopyToDataTable();
return dtMerged;
}
it gives "The source contains no DataRows" when Data tables does not contain Matched Records...
How to rectify it..pls give your suggistions
Two ways:
either check if it contains rows with Enumerable.Any before you call CopyToDataTable
use dtfff.Clone to create an empty DataTable with the same schema as the source table and use a loop to fill it from the LINQ query.
First approach:
var rows = from a in dtfff.AsEnumerable()
join b in dtff.AsEnumerable()
on a["contacts"].ToString() equals b["contacts"].ToString()
into g
where g.Count() > 0
select a;
DataTable merged;
if (rows.Any())
merged = rows.CopyToDataTable();
else
merged = dtfff.Clone();
return merged;
Second approach:
DataTable merged = dtfff.Clone();
foreach (DataRow sourceRow in rows)
{
merged.ImportRow(sourceRow); // or add all fields manually
}
return merged;
I prefer the second approach since it only needs to execute the query once.

Linq query on large datatable

I have a 2 datatables which I have created a join. I can then copy this back to a new datatable. This is fine and works without issue. However, if I have a datatable with a larger number of columns, say 30 with various datatypes, how can I copy them all to a new datatable without specifying each column, i.e. similar to a SQL query ?
Thanks.
var results = from table1 in dt.AsEnumerable()
join table2 in names.AsEnumerable()
on table1.Field<int>("Id") equals table2.Field<int>("Id")
select new
{
C1 = table1.Field<int>("Id"),
C2 = table1.Field<int>("Col1"),
C3 = table1.Field<int>("Col2"),
C4 = table2.Field<String>("Name")
};
DataTable sout = dt.Clone();
sout.Columns.Add("Name", typeof(string));
foreach (var v in results)
{
sout.Rows.Add(v.C1,v.C2,v.C3,v.C4);
};
First set primary keys for your tables.
dt.PrimaryKey = new[] {dt.Columns["Id"]};
names.PrimaryKey = new[] { names.Columns["Id"] };
Then, if you don't mind dt changing you can merge tables with the code,
dt.Merge(names,false, MissingSchemaAction.AddWithKey);
If you mind clone dt and do the same.

ToTable() doesn't return distinct records?

I am using datatable to return me distinct records but somehow its not returning me distinct records
I tried like
dt.DefaultView.ToTable(true, "Id");
foreach (DataRow row in dt.Rows)
{
System.Diagnostics.Debug.Write(row["Id"]);
}
It still returns me all the records. What could be wrong here?
UPDATE
My sql is as below
select t.Update ,t.id as Id, t.name ,t.toDate,t.Age from tableA t Where t.Id = 55
union
select t.Update ,t.id as Id, t.name ,t.toDate,t.Age from tableB t Where t.Id = 55
order by Id
Its very hard to do distinct in my query as there are many columns than mentioned here.
If you use a database it would be better to use sql to return only distinct records(e.g. by using DISTINCT, GROUP BY or a window function).
If you want to filter the table in memory you could also use Linq-To-DataSet:
dt = dt.AsEnumerable()
.GroupBy(r=>r.Field<int>("Id")) // assuming that the type is `int`
.Select(g=>g.First()) // take the first row of each group arbitrarily
.CopyToData‌​Table();
Note that the power of Linq starts when you want to filter these rows or if you don't want to take the first row of each id-group arbitrarily but for example the last row(acc. to a DateTime field). Maybe you also want to order the groups or just return the first ten. No problem, just use OrderBy and Take.
The issue is that you're not grabbing the new table:
var newDt = dt.DefaultView.ToTable(true, "Id");
foreach (DataRow dr in newDt.Rows) ...
the ToTable method doesn't modify the existing table - it creates a new one.
DataView view = new DataView(table);
DataTable distinctValues = view.ToTable(true, "Id");
you are not assigning the return value to any variable, try this
DataTable dtnew = dt.DefaultView.ToTable(true, "Id");
foreach (DataRow row in dtnew.Rows)
{
System.Diagnostics.Debug.Write(row["Id"]);
}

Categories