How do I compare values of one data set from another.
1st dataset ["proper records"] is coming from SQL Server with column names
[id], [subsNumber]
2nd dataset ["proper and inproper records"] is coming from progress database, with different columns except 1 which is subsNumber
How do I go and make another dataset which has all the [subsNumber] from ["proper records"] with matching records from 2nd datset ["proper inproper records"] ?
or
delete all the records in 2nd dataset["proper and inproper records"] which don't match the "subsNumber" column in the 1st dataset
or any other idea
basically How do I get all records from 2nd dataset which has same "subsNumber" as the 1st dataset
The key is using System.Data.DataRelation to join your 2 datatables on a common column (or columns).
Here's some code derived from a post at KC's See Sharp Blog
public DataTable GetImproperRecords(DataTable ProperRecords, DataTable ImproperRecords) {
DataTable relatedTable = new DataTable("Difference");
try {
using (DataSet dataSet = new DataSet()) {
dataSet.Tables.AddRange(new DataTable[] { ProperRecords.Copy(), ImproperRecords.Copy() });
DataColumn properColumn = new DataColumn();
properColumn = dataSet.Tables[0].Columns[1]; // Assuming subsNumber is at index 1
DataColumn improperColumn = new DataColumn();
improperColumn = dataSet.Tables[1].Columns[0]; // Assuming subsNumber is at index 0
//Create DataRelation
DataRelation relation = new DataRelation(string.Empty, properColumn, improperColumn, false);
dataSet.Relations.Add(relation);
//Create columns for return relatedTable
for (int i = 0; i < ImproperRecords.Columns.Count; i++) {
relatedTable.Columns.Add(ImproperRecords.Columns[i].ColumnName, ImproperRecords.Columns[i].DataType);
}
relatedTable.BeginLoadData();
foreach (DataRow parentrow in dataSet.Tables[1].Rows) {
DataRow[] childrows = parentrow.GetChildRows(relation);
if (childrows != null && childrows.Length > 0)
relatedTable.LoadDataRow(parentrow.ItemArray, true);
}
relatedTable.EndLoadData();
}
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
}
return relatedTable;
}
I solved the problem:
1st dataset--> loop throuhg and get the subsNumber
Call function and pass subsNumber and 2nd dataset--> to it
Then start another loop for new dataset
Continue if subsnumber don't match
If subsNumber match work on that data like add columns to sqlserver table etc.
code:
foreach (DataRow row in ecommDS.Tables["EcommData"].Rows)
{
//string statCode = ""
string prdCode = ""; //declaring var for getting string format from ecomm
string checking = "";
prdCode = row["PRD-CDE"].ToString();
checking = row["SUBS-NUM"].ToString();
if(checking != subsNum)
{
continue;
}
To get all the records from 2nd dataset that match the records from the 1st dataset would be something like this:
IEnumerable list3 = list2.Where(l2=>list1.Contains(l1=>l1.subsNumber == l2.subsNumber));
Something along those lines!
Related
From this code I am trying to only display data rows that contain the fields "DBY" in the Station_From_Code column and "MAT" in the Station_To_Column. This will then be printed onto a HTML page. These fields are definitely in the datatable but when I run this cod the table is empty. I am not used to working with data tables in C# so apologies for the poor coding.
dynamic schedluedContent = JsonConvert.DeserializeObject(scheduledJson);
JArray items2 = new JArray();
foreach (JObject stops in schedluedContent.stops)
{
DataTable dt = new DataTable();
DataRow dr;
dr = dt.NewRow();
dr["From_Station_Code"] = stops["station_code"];
dr["To_Station_Code"] = stops["station_code"];
dt.Rows.Add(dr);
DataRow[] result = dt.Select("From_Station_Code = 'DBY' AND To_Station_Code = 'MAT'");
dt.Rows.Add(result);
GridViewTrainTimes.DataSource = dt;
GridViewTrainTimes.DataBind();
}
It's a long time I have not seen this style of code for working with database tables! EntityFramework comes to change and surely ease the way of working with database and prevent different risks of using SQL commands inside the code.
If you use EF, your code will become something like bellow:
var rows = myDBContext.MyTable.Where(x=>x.From_Station_Code == "DBY" && x.To_Station_Code == "MAT");
GridViewTrainTimes.DataSource = rows;
You can use find match rows and add in new datatable, that contains only your match rows data then you can bind this dt to gridview.
DataTable dt = new Datatable(); // Lets this datatable have data;
Datatable dt2 = new Datatable(); // Copy all matching rows
foreach (DataRow dr in dt.Rows)
{
if (dr["From_Station_Code"].ToString() == "DBY" && dr["To_Station_Code"].ToString() == "MAT")
{
dt2.Rows.Add(dr);
}
}
GridViewTrainTimes.DataSource = dt;
GridViewTrainTimes.DataBind();
If I want to compare two datatables and get the difference in new datatable but I want to keep an uncompared column.
example:
first Datatable
Name | Number
---- |-------
Jude | 12
Mark | 14
Bin | 15
second Datatable
Name
------
Jude
Robin
Kamil
the Datatable must have:
Name | Number
-------|----------
Mark | 14
Bin | 15
I have this method which can compare the two datatables and get the difference, but how can I get the number.
public static DataTable CompareTables(DataTable first, DataTable second)
{
first.TableName = "FirstTable";
second.TableName = "SecondTable";
//Create Empty Table
DataTable table = new DataTable("Difference");
try
{
//Must use a Dataset to make use of a DataRelation object
using (DataSet ds = new DataSet())
{
//Add tables
ds.Tables.AddRange(new DataTable[] { first.Copy(), second.Copy() });
//Get Columns for DataRelation
DataColumn[] firstcolumns = new DataColumn[1];
firstcolumns[0] = ds.Tables[0].Columns[0];
DataColumn[] secondcolumns = new DataColumn[1];
secondcolumns[0] = ds.Tables[1].Columns[0];
//Create DataRelation
DataRelation r = new DataRelation(string.Empty, firstcolumns, secondcolumns, false);
ds.Relations.Add(r);
//Create columns for return table
for (int i = 0; i < first.Columns.Count; i++)
{
table.Columns.Add(first.Columns[i].ColumnName, first.Columns[i].DataType);
}
//If First Row not in Second, Add to return table.
table.BeginLoadData();
foreach (DataRow parentrow in ds.Tables[0].Rows)
{
DataRow[] childrows = parentrow.GetChildRows(r);
if (childrows == null || childrows.Length == 0)
table.LoadDataRow(parentrow.ItemArray, true);
}
table.EndLoadData();
}
}
catch (Exception ex)
{
}
return table;
}
Let the database handle these things:
SELECT name, number from table1 where name not in (select name from table2);
public static DataTable CompareTables(DataTable first, DataTable second)
{
second.PrimaryKey = new DataColumn[] {second.Columns["Name"]};
DataTable difference = second.Clone();
foreach (DataRow row in first.Rows) {
if (second.Rows.Find(row["Name"]) == null)
{
difference.ImportRow(row);
}
}
return difference;
}
#user3527065 your code will throw an argument exception as the no. of columns has to be same .
DataRelation r = new DataRelation(string.Empty, firstcolumns, secondcolumns, false);
I your case firstcolumns has 2 columns whereas second columns has 1 column so it would throw an argument exception.
How can I filter data from dataset to datatable?
like the code->
DataRow[] dr = DS.Tables[0]
.Select("STAGENAME='Develop' AND DEVLAPSEDAYS IS NOT NULL");
How can I use datatable here?
following code doesn`t reflect changes->
DataTable FilteredDataD = DS.Tables[0];
if (FilteredDataD.Rows.Count > 0) {
FilteredDataD.DefaultView.RowFilter = "STAGENAME='Develop' AND DEVLAPSEDAYS IS NOT NULL";
FilteredDataD.DefaultView.ToTable();
}
Is is possible to remove a column using above filter,like "STAGENAME='Develop' AND DEVLAPSEDAYS IS NOT NULL" + FilteredDataD.column("col_name")...
Suppose I have 5 columns display only 4,I can`t remove col_name from my query.Is there a way?
Reply
Try using LINQ instead:
var table = DS.Tables[0].AsEnumerable().Where(
r => r.Field<string>("STAGENAME") == "Develop" && r.Field<int?>("DEVLAPSEDAYS").HasValue).AsDataView().ToTable();
EDIT Changed AsDataView to AsDataView() for syntactical accuracy.
EDIT Provided .NET 2.0 compatible solution
DataTable table = DS.Tables[0];
if (table.Rows.Count > 0)
{
table.DefaultView.RowFilter = "STAGENAME = 'DEVELOP' AND DEVLAPSEDAYS IS NOT NULL";
table = table.DefaultView.ToTable();
}
You could write an extension method (using C# 3) like follows:
public static DataTable Filter(this DataTable dataTable, string selectFilter)
{
var filteredTable = dataTable.Clone();
var rows = dataTable.Select(selectFilter).ToList();
rows.ForEach(filteredTable.ImportRow);
return filteredTable;
}
Then use it like follows:
DataTable dataTable = DS.Tables[0]
.Filter("STAGENAME='Develop' AND DEVLAPSEDAYS IS NOT NULL");
Update, since you said you are using C# 2.0 (and thus extension methods and LINQ aren't an option) you could use this instead:
public static DataTable GetFilteredTable(
DataTable sourceTable, string selectFilter)
{
var filteredTable = sourceTable.Clone();
var rows = sourceTable.Select(selectFilter);
foreach (DataRow row in rows)
{
filteredTable.ImportRow(row);
}
return filteredTable;
}
DataTable dataTable = GetFilteredTable(
DS.Tables[0], "STAGENAME='Develop' AND DEVLAPSEDAYS IS NOT NULL");
I am using DataRelation to compare two DataTable and return a third table containing the rows that are not share by both original tables by using this tutorial. Below is the code.
public static DataTable Difference(DataTable First, DataTable Second)
{
//Create Empty Table
DataTable table = new DataTable("Difference");
//Must use a Dataset to make use of a DataRelation object
using(DataSet ds = new DataSet())
{
//Add tables
ds.Tables.AddRange(new DataTable[]{First.Copy(),Second.Copy()});
//Get Columns for DataRelation
DataColumn[] firstcolumns = new DataColumn[ds.Tables[0].Columns.Count];
for(int i = 0; i < firstcolumns.Length; i++)
{
firstcolumns[i] = ds.Tables[0].Columns[i];
}
DataColumn[] secondcolumns = new DataColumn[ds.Tables[1].Columns.Count];
for(int i = 0; i < secondcolumns.Length; i++)
{
secondcolumns[i] = ds.Tables[1].Columns[i];
}
//Create DataRelation
DataRelation r = new DataRelation(string.Empty,firstcolumns,secondcolumns,false);
ds.Relations.Add(r);
//Create columns for return table
for(int i = 0; i < First.Columns.Count; i++)
{
table.Columns.Add(First.Columns[i].ColumnName, First.Columns[i].DataType);
}
//If First Row not in Second, Add to return table.
table.BeginLoadData();
foreach(DataRow parentrow in ds.Tables[0].Rows)
{
DataRow[] childrows = parentrow.GetChildRows(r);
if(childrows == null || childrows.Length == 0)
table.LoadDataRow(parentrow.ItemArray,true);
}
table.EndLoadData();
}
return table;
}
Surprisingly enough when I exercised this code, it only worked on few cases and failed in others.
There was one case, I was comparing two identical table (but has different source) that both has:
Same Column Name & DataType
Same Number of Rows & Columns
Same Value in Each Cells
Only to have a brand new table returned that actually has the exact same composition as the two original tables!
What did I possibly miss?
Is it possible that two identical tables (sharing features I mentioned above) can have other different properties (which doesn't seem visible to users' eyes)?
Or is it possible that this is actually a bad method? What are the possible alternatives?
EDITED
Both tables have same primitive datatype such as: System.String, System.Int32, System.DateTime
These code doesn't work on all samples I tested
Here is a print screen of 1 sample (using DataSet Visualizer)
I had to write something similar once and this is the approach I used:
First this approach only works if you don't have duplicate rows in each table.
Using primary keys..
First.PrimaryKey = firstcolumns;
Second.PrimaryKey = secondcolumns; //These throw exceptions when you have duplicate rows
Then..
foreach (DataRow dr in Second.Rows)
{
List<Object> l = new List<Object>();
foreach (DataColumn dc in secondcolumns) l.Add(dr[dc]);
if (First.Rows.Find(l.ToArray()) == null) //NOT FOUND
{
table.Rows.Add(l.ToArray());
}
}
foreach (DataRow dr in First.Rows)
{
List<Object> l = new List<Object>();
foreach (DataColumn dc in firstcolumns) l.Add(dr[dc]);
if (Second.Rows.Find(l.ToArray()) == null) //NOT FOUND
{
table.Rows.Add(l.ToArray());
}
}
Cheers,
I have the following method which returns dataset. I am using .NET 2.0
DataSet ds = GetAllRecords();
I want to get values from each column for a particular row and bind it to a variable.
How can this be achieved?
currently the method returns all the row from the table and I have to find that particular row based on ID.
However, if that is not possible I can come with
DataSet ds = GetSpecificRecord(id);
But I still need to get values from each column and bind it to variable.
Please advice.
// Create a table
DataTable table = new DataTable("users");
table.Columns.Add(new DataColumn("Id", typeof(int)));
table.Columns.Add(new DataColumn("Name", typeof(string)));
table.Rows.Add(1, "abc");
table.Rows.Add(2, "ddd");
table.Rows.Add(3, "fff");
table.Rows.Add(4, "hhh d");
table.Rows.Add(5, "hkf ds");
// Search for given id e.g here 1
DataRow[] result = table.Select("Id = 1"); // this will return one row for above data
foreach (DataRow row in result)
{
Console.WriteLine("{0}, {1}", row[0], row[1]);
}
This will get you the value from Row 0 obviously you would need to modify for multiple rows returned
long id = ds.Tables[0].Rows[0].Field<long>("ID");
You can do this with LINQ.
DataRow resultRow = ds.Tables["SomeTable"].AsEnumerable().Where(row => row.Field<int>("SomeID") == 1).FirstOrDefault();
For .NET 2.0 and below
If your DataTable has a primary key defined, you can find the row like this:
DataTable table = ds.Tables["SomeTable"];
DataRow row = table.Rows.Find(1);
If there is no primary key, you can assign one like this:
DataTable table = ds.Tables["SomeTable"];
table.PrimaryKey = new DataColumn[] { table.Columns["SomeID"] };
DataRow row = table.Rows.Find(1);
Another option is to use the RowFilter property of the DefaultView, like this:
DataTable table = ds.Tables["SomeTable"];
table.DefaultView.RowFilter = "SomeID == 1"; //not sure if it's == or = here
DataRow row = table.DefaultView[0].Row;
Lastly, you can also use the DataTable.Select() method to find rows.
Have you looked at using a typed dataset? If you're looking for a row based on the primary key of a table it will autogenerate a method for you to get a row by ID and it will be strongly typed so you can get column values by name.
They were quite handy in .Net 2.0 - but LINQ made them fairly obsolete.
Edit: A slightly better reference URL
http://www.c-sharpcorner.com/UploadFile/rupadhyaya/TypedDataSets12032005021013AM/TypedDataSets.aspx
We can get value from dataset by using this easy method:
System.Data.DataSet ds = db.MySelect(
"Fields",
"Table",
"Condition"
);
if (ds != null)
{
if (ds.Tables[0].Rows.Count > 0)
{
object value=Tables[0].Rows[indx]["field name"];
}
}
To fetch values from student table and display it in console window.
class Class1
{
static void Main(string[] args)
{
SqlConnection con=new SqlConnection(<connectionstring>);
SqlCommand cmd = new SqlCommand("select * from Student", con);
SqlDataAdapter ad = new SqlDataAdapter(cmd);
DataSet ds=new DataSet();
ad.Fill(ds);
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
try
{
DataRow r = ds.Tables[0].Rows[i];
Console.WriteLine(r.Field<Int32>(0));
Console.WriteLine(r.Field<String>(1));
Console.WriteLine(r.Field<String>(2));
Console.WriteLine(r.Field<Decimal>(3));
Console.WriteLine(r.Field<Int16>(4));
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
Console.ReadKey();
}
}
sql Student table Info
Id int
Name varchar(50)
EmailId nvarchar(50)
MobileNo numeric(10,0)
Standard smallint