I have a datatable in C# called "table" that looks like the following:.
ID Value
10 A
20 B
30 C
(It really has about 1200 rows, but I tried to simplify it)
My goal is to be able to print specific rows in this datatable. For example, if I would like to print the second row (row index 1) I would use the following:
Response.Write(table.Rows[1]["Value"].ToString());
This prints out the value "B" which is what I want, but is there a way to use the "ID" column to print that specific value instead of using the row index of 1. I would like to be able to link ID 10 and Value B together somehow.
If ID is defined as the primary key, this should look up B by its ID key:
Response.Write(table.Rows.Find(20).["Value"].ToString());
If ID isn't setup as a PK (or you want to query another field), you could use a Linq query
var chosenRow = (from row in table.AsEnumerable()
where row.Field<int>("ID") == 10
select row).First();
chosenRow is the first DataRow object that meets the criteria set in the where clause. So you could just:
Response.Write(chosenRow["Value"].ToString());
you can loop trough your datatable using for each, and when the ID equals 10, then you do what you want
would be something like this:
for each row as datarow in datatable.rows
if row.Items["ID"] = 10 Then
//do something
end if
Related
What would be the right way to avoid duplication when querying datatable and then saving it to DataTable. I'm using the pattern below, which gets very error-prone once tables grow. I looked at below hints. With first one copyToDataTable() looks not really applicable and second is for me much too complex for the task. I would like to split the below code into 2 separate methods (first to build the query and second to retrieve the DataTable). Perhaps if I avoid the anonymous type in the query this should be easier to avoid hardcoding all the column names - but I'm somehow lost with this.
Filling a DataSet or DataTable from a LINQ query result set
or
https://msdn.microsoft.com/en-us/library/bb669096%28v=vs.110%29.aspx
public DataTable retrieveReadyReadingDataTable()
{
DataTable dtblReadyToSaveToDb = RetrieveDataTableExConstraints();
var query = from scr in scrTable.AsEnumerable()
from products in productsTable.AsEnumerable()
where(scr.Field<string>("EAN") == products.Field<string>("EAN"))
select
new
{
Date = DateTime.Today.Date,
ProductId = products.Field<string>("SkuCode"),
Distributor = scr.Field<string>("Distributor"),
Price = float.Parse(scr.Field<string>("Price")),
Url = scr.Field<string>("Url")
};
foreach (var q in query)
{
DataRow newRow = dtblReadyToSaveToDb.Rows.Add();
newRow.SetField("Date", q.Date);
newRow.SetField("ProductId", q.ProductId);
newRow.SetField("Distributor", q.Distributor);
newRow.SetField("Price", q.Price);
newRow.SetField("Url", q.Url);
}
return dtblReadyToSaveToDb;
}
Firstly, you have to decide what "duplicate" means in your case. According to your code i would say a duplicate is a row with the same value in column Date, ProductId and Distributor. So add a multi column primary key for those columns first.
Secondly, you should add some sort of code that first queries existing rows and then compares these existing rows to the rows you want to create. If a match is found, then simply just don't insert a new row.
I am trying to compare two datatable and return only rows which has changes. In the below code I am cloning dt2 into dt3 but it doesn't pick the rows with changes instead it puts everything in there. Pls suggest some options.
Even if a single cell value is modified then I need to pick that row. Both datatable with have same set of rows and column each time I compare.
Table 1 Table 2
ID Name ID Name
1 Mark 1 Mark
2 Spencer 2 Spencer
3 Ryan 3 George
Table 3 Expected Result:
ID Name
3 George
CODE:
DataTable dt3 = new DataTable();
// It will compare the 2nd table with the 1st table
var contacts = dt2.AsEnumerable().Except(dt1.AsEnumerable(), DataRowComparer.Default);
dt3 = dt2.Clone();
foreach (DataRow rows in contacts)
{
dt3.ImportRow(rows);
}
You do not need two tables for this purpose. Simply calling GetChanges() on the second DataTable will get you the last row that has changed. Make sure you haven't (directly or indirectly) called AcceptChanges() on the DataTable, otherwise GetChanges() won't return anything.
DataRow exposes a property named RowState that is set to Modified when one or more columns of it get changed. AcceptChanges() and RejectChanges() reset this flag back to Unmodified.
You can even get the original value (Ryan in your case) and current value (George in your case) of a column by calling the indexer of DataRow with the second parameter (RowVersion) set to Original and Current respectively.
Try this:
dt1.Select()
.Join(dt2.Select(), x => x["Id"], y => y["Id"], (x, y) => new { x, y })
.Where(z => z.x["Name"] != z.y["Name"])
.Select(z => z.y);
Here dt1 is Table 1 and dt2 is Table 2.
It tries to join tables by Id, and then filters out records with same Name.
The code below is returning a value of 0 every time. I am trying to filter a datatable and get the number of rows. To illustrate the example here, I am setting the criteria as the value 250 to be looked for in my ID column in Table2.
How can I fix it?
var count = (from row in MyDatabaseDataSet.Tables["Table2"].AsEnumerable() where string.Equals(row["ID"].ToString(), 250)) select row).Count();
MessageBox.Show(Convert.ToString(count));
Try that one:
var count = (from row in MyDatabaseDataSet.Tables["Table2"].AsEnumerable()
where row.Field<int>("ID") == 250
select row).Count();
With method syntax:
int rowCount = MyDatabaseDataSet.Tables["Table2"].AsEnumerable()
.Count(r => r.Field<int>("ID") == 250);
Ok emmmmmmm well this is... awkward... I absolutely forgot to fill the dataset with the second table before calling the code. Here's what I had forgotten:
// TODO: This line of code loads data into the 'showsDatabaseDataSet.AllEpisodes' table. You can move, or remove it, as needed.
this.MyTableAdapter.Fill(this.MyDatabaseDataSet.Table2);
It is now working thanks guys!
I have datatable1 which has 11 columns and 100,000 rows.. I would like to do a check to see if the text in column one starts with "one" and if it does, add that row into the second datatable. I have done the below but yet still it does not work.. I get the error that the row belong to another table
foreach (DataRow r in queryDataTable.Rows)
{
if (r[0].ToString().StartsWith(queryString))
{
dt.ImportRow(r);
}
}
You cannot directly import the row of one table into another datatable. You need to create a new row and then copy the row.
Try this -
dt.Rows.Add(r.ItemArray)
Instead of your for loop, you may use LINQ to select those rows which StartsWith queryString and then you can use CopytoDataTable method to create a new table for the selected rows.
var NewTable = queryDataTable.AsEnumerable()
.Where(r => r.Field<string>(0).StartsWith(queryString))
.CopyToDataTable();
Remember to include using System.Linq; at the top.
I have a DataSet similar to the one below:
ID Name Data1 Data2
1 MM X 1000
2 ST Y 1000
3 EC Z 1000
4 JT T 1000
I display this DataSet in a DataGridView by binding the DataSet. What I would like to do is set the visibility of the Data2 column based on if all the data is similar or not.
So in the above example, I would want to hide the Data2 column because the data represented is common to all elements in the DataSet. But if any of the elements had a unique entry for that column, I would want the column to be visible.
Is there a way to do this without iterating over the DataSet? I prefer not to iterate as my DataSets are quite large and I want to perform this check for multiple columns.
You can use some LINQ to check to see how many distinct values you have in that column:
if(dataTable.AsEnumerable().Select(row => row["Data2"]).Distinct().Count() > 1)
{
// Make column invisible
}
If there is more than 1 distinct value, then you know that not all of the values are equal.
var areSame = dt.Rows.Count > 0 &&
dt.AsEnumerable().All(x => dt.rows[0]["Data2"].Equlas(x["Data2"]));