I have a DataSet where I need to find out how many rows has been changed using the following code:
dataTable1 = dataSet1.Tables["FooTable"].GetChanges();
foreach (DataRow dr in dataTable1)
{
// ...
}
DataSet has DataSet.HasRow but DataTable doesn't have such method. If there is no changed rows. changedDT1 will be a null value, causing the loop to throw exception.
How do I check if DataTable is empty? I tried Rows.Count - doesn't work...
First make sure that DataTable is not null and than check for the row count
if(dt!=null)
{
if(dt.Rows.Count>0)
{
//do your code
}
}
If dataTable1 is null, it is not an empty datatable.
Simply wrap your foreach in an if-statement that checks if dataTable1 is null.
Make sure that your foreach counts over DataTable1.Rows or you will get a compilation error.
if (dataTable1 != null)
{
foreach (DataRow dr in dataTable1.Rows)
{
// ...
}
}
Normally when querying a database with SQL and then fill a data-table with its results, it will never be a null Data table. You have the column headers filled with column information even if you returned 0 records.When one tried to process a data table with 0 records but with column information it will throw exception.To check the datatable before processing one could check like this.
if (DetailTable != null && DetailTable.Rows.Count>0)
Don't use rows.Count. That's asking for how many rows exist. If there are many, it will take some time to count them. All you really want to know is "is there at least one?" You don't care if there are 10 or 1000 or a billion. You just want to know if there is at least one. If I give you a box and ask you if there are any marbles in it, will you dump the box on the table and start counting? Of course not. Using LINQ, you might think that this would work:
bool hasRows = dataTable1.Rows.Any()
But unfortunately, DataRowCollection does not implement IEnumerable.
So instead, try this:
bool hasRows = dataTable1.Rows.GetEnumerator().MoveNext()
You will of course need to check if the dataTable1 is null first. if it's not, this will tell you if there are any rows without enumerating the whole lot.
You can also simply write
if (dt.Rows.Count == 0)
{
//DataTable does not contain records
}
This is an old question, but because this might help a lot of c# coders out there, there is an easy way to solve this right now as follows:
if ((dataTableName?.Rows?.Count ?? 0) > 0)
As from MSDN for GetChanges
A filtered copy of the DataTable that can have actions performed on it, and later be merged back in the DataTable using Merge. If no rows of the desired DataRowState are found, the method returns Nothing (null).
dataTable1 is null so just check before you iterate over it.
Sub Check_DT_ForNull()
Debug.Print WS_FE.ListObjects.Item(1).DataBodyRange.Item(1).Value
If Not WS_FE.ListObjects.Item(1).DataBodyRange.Item(1).Value = "" Then
Debug.Print WS_FE.ListObjects.Item(1).DataBodyRange.Rows.Count
End If
End Sub
This checks the first row value in the DataBodyRange for Null and Count the total rows
This worked for me as I downloaded my datatable from server It had not data's but table was created with blanks and Rows.Count was not 0 but blank rows.
bool empty = !DataTableExtensions.AsEnumerable(DataTableToCheck).Any()
Related
We have a function which does the following
Given a DataRow
Creates a clone of the dataset
Imports the given row in the clone
So far, we never had any issue with this. But, there is a condition which has occured where in, the row which is created after import is skipping/nulling out some values.
I have really no clue as to why this is happening
private DataSet GetFullDataSetForCurrentRow(DataRow currentRow)
{
DataSet clone = null;
if (currentRow != null)
{
clone = currentRow.Table.DataSet.Clone();
// Get the parent row.
DataRow rootRow = GetRootRow(currentRow);
// Import the root row in the clone.
clone.Tables[rootRow.Table.TableName].ImportRow(rootRow);
// additonal code skipped...
}
return clone;
}
So, the rootRow has the correct values, but if i inspect the imported row, its loosing/skipping some values.
Check the screenshots.
https://i.imgur.com/92bLi2R.png
https://i.imgur.com/JIyHr4r.png
Found the problem.
The value that was being set in the column was larger than the size of the column.
An exception was generated but swallowed.
Thus, while importing the row, it skipped those values.
I am really not sure, how the values were stored in the first place though. Because there was an exception, it should have ideally not stored the value.
I want to do this:
public void UpdateDataRowsToDataTable(string tableName, List<DataRow> rows)
{
foreach (DataRow row in rows)
{
// this method does not exist!!
_dataSet.Tables[tableName].Rows.Update(row);
}
}
I need a method that finds a row (maybe by primary key) and updates changed rows to the row in DataTable.
The only possibility what I know is to use Select (or Find) and then maybe iterate all columns and give them new values. Please tell me that this cannot be true!
Although the question is not quite clear it sounds like you have a group of rows from one table and want to update the equivalent rows in another datatable. If this is the case they you can just use the find method and manually update them as you suggested, or alternatively, add the new rows to another table and merge them (there are all sorts of options for merging two data tables). Merging however will just do the same thing under the hood (i.e. find by primary key and update the columns).
Another way would be to just replace the row and set its status to modified datarow.SetModified()
Or you can delete the old one and add the new one...
Could you use boxing to do that if your datatables are the same.
DestDataset.DestDataTable newChildRecords =
(DestDataset.DestDataTable)_dataset.Tables[tableName].GetChanges(DataRowState.Added);
If you are using dataAdapter...
foreach (DataRow row in rows)
{
Row.BeginEdit();
//Do your stuff
Row.EndEdit();
}
dataAdapter.Update(_dataSet, "yourTable");
Another option is to use the ItemArray property to update the DataRow instance. The only thing is that you still have to select the proper rows. Also, note that you have to change the whole ItemArray instead of its elements in order to have the modification reflected in the DataTable.
foreach (DataRow row in rows)
{
// Select the row
var rows = _dataSet.Tables[tableName].Select(string.Format("Table_ID = {0}", row["Table_ID"]));
// Update the row
if (0 < rows.Length)
rows[0].ItemArray = (object[])row.ItemArray.Clone();
}
Regardless of the way you chose to update the DataRow, you can put the whole thing in an extension method.
To whom this may concern, I have searched a considerable amount of time, to work a way out of this error
"Deleted row information cannot be accessed through the row"
I understand that once a row has been deleted from a datatable that it cannot be accessed in a typical fashion and this is why I am getting this error. The big issue is that I am not sure what to do to get my desired result, which I will outline below.
Basically when a row in "dg1" is deleted the row beneath it takes the place of the deleted row (obviously) and thus inherits the deleted rows index. The purpose of this method is to replace and reset the rows index (via grabbing it from the corresponding value in the dataset) that took the deleted rows place and as such the index value.
Right now I am just using a label (lblText) to try and get a response from the process, but it crashes when the last nested if statement trys to compare values.
Here is the code:
void dg1_Click(object sender, EventArgs e)
{
rowIndex = dg1.CurrentRow.Index; //gets the current rows
string value = Convert.ToString(dg1.Rows[rowIndex].Cells[0].Value);
if (ds.Tables[0].Rows[rowIndex].RowState.ToString() == "Deleted")
{
for (int i = 0; i < dg1.Rows.Count; i++)
{
if (Convert.ToString(ds.Tables[0].Rows[i][0].ToString()) == value)
// ^ **where the error is occurring**
{
lblTest.Text = "Aha!";
//when working, will place index of compared dataset value into rowState, which is displaying the current index of the row I am focussed on in 'dg1'
}
}
}
Thanks ahead of time for the help, I really did search, and if it is easy to figure out through a simple google search then allow myself to repeatably hate on me, because I DID try.
gc
You can also use the DataSet's AcceptChanges() method to apply the deletes fully.
ds.Tables[0].Rows[0].Delete();
ds.AcceptChanges();
The current value for the data column in the inner if statement will not be available for deleted rows. To retrieve a value for deleted rows, specify that you want the original value. This should fix your error:
if (Convert.ToString(ds.Tables[0].Rows[i][0, DataRowVersion.Original].ToString()) == value)
In your "crashing if", you can check if the row is deleted before accessing it's values :
if (ds.Tables[0].Rows[i].RowState != DataRowState.Deleted &&
Convert.ToString(ds.Tables[0].Rows[i][0].ToString()) == value)
{
// blaaaaa
}
Also, I'm not sure why you ToString() the RowState instead of comparing it to DataRowState.Deleted.
after deleting the row , rebind your grid with the datatable , no need to manually resetting index , datatable handels it.
so you onl;y need to rebind grid's datasource.
I'm trying to figure out where DataRowCollection.Add(DataRow row) inserts the new row into its datatable. Is it at the end of the table, like an append? Is it random?
Also, I want to use this while I'm for looping through a datatable. If some condition exists, add a new row containing different data to run through the For loop to the end of the datatable. Are there any specific problems with this approach? How else might I handle it?
EDIT: I am For Looping through a .Net DataTABLE stored in memory. I'm not touching the dataBASE where the original data is stored during this looping operation. The DataTABLE is populated prior to the loop and is not a problem.
Here is relavant code:
DataTable machineANDlastDate = new DataTable();
//Populate machineANDlastDate
for (int i = 0; i < machineANDlastDate.Rows.Count; i++)
{
lastFutureDate = DateTime.Parse(machineANDlastDate.Rows[i]["MaxDueDate"].ToString());
newDateTime = lastFutureDate.AddDays(frequency); //This is where the new date is created.
machineSerial = machineANDlastDate.Rows[i]["machineSerial"].ToString();
if (newDateTime < DateTime.Now)
{
machineANDlastDate.Rows.Add(new String[] { machineSerial, newDateTime.AddDays(frequency).ToString() });
continue;
}
...Removed for irrelevancy...
}
Is this a valid way to add a row to the end of the datatable?
As far as I know, it is always added to the end of the collection.
If you for loop through the database, there shouldn't be a problem, if you begin at the beginning of the data table and finish at the end of it or smth similar. However, you will then also loop through the newly created data rows, and I don't know whether you want to achieve this. You only could get problems if you take a foreach loop instead because it cannot handle modifications of the underlying collection.
If you want to know if a row is new or not you can check the DataRow.RowState property.
// your code to add rows
...
// process added rows
foreach (DataRow row in machineANDlastDate.Rows)
{
if (row.RowState == DataRowState.Added)
{
// do stuff
}
}
// now confirm new rows (they won't have a RowState of Added after this)
machineANDlastDate.AcceptChanges();
It's always at the end of the table, as far as i know most of the DataBase conectors, whe you use their add row, its always at the end.
The Add method will insert a DataRow into a DataRowCollection object only. To actually add the DataRow to the data table, you will need to call the NewRow method which appends itself onto the DataTable, and thus appends the row to the table in that database. For reference, check out http://msdn.microsoft.com/en-us/library/9yfsd47w.aspx
Using C#
I have a datareader that return a lsit of records from a mysql database.
I am trying to write code that checks if the datareader isnull. The logic behind this is: If the datareader having field then display the info otherwise hide the field.
I have tried:
cmd1 = new OdbcCommand("Select * from tb_car where vehicleno = '" + textbox2.text + "';", dbcon);
dr1 = cmd1.ExecuteReader();
if (dr1["tb_car"]. != DBNull.Value)
{
textbox1.Text = "contains data";
}
else
{
textbox1.Text = "is null";
}
The above code gives me this error:
Exception Details: System.IndexOutOfRangeException: Additional
Any help would be greatly appreciated...
I see a few problems here... First, it looks like you're trying to access the table name in the line:
if(dr1["tb_car"] != DBNull.Value
You should be passing a FIELD NAME instead of the table name. So if the table named "tb_car" had a field called CarId, you would want to have your code look like:
if(dr1["CarId"] != DBNull.Value)
If I'm right, then there is probably no field named "tb_car", and the Index is Out of Range error is because the DataReader is looking for an item in the column collection named "tb_car" and not finding it. That's pretty much what the error means.
Second, before you can even check it , you have to call the DataReader's Read() command first to read a line from the database.
so really your code should look like...
while(dr.Read())
{
if(dr1["CarId"] != DBNull.Value)
{
....
and so on.
See here for the proper use of a DataReader: http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.read.aspx
Finally, if you're just checking to see if there are any rows in the table, you can ignore all of the above and use the HasRows property as in
if(dr.HasRows)
{
....
although if you're using the while(dr.Read()) syntax, the code in the while loop will only execute if there are rows in the first place, so the HasRows could potentially be unnecessary if you don't want to do anything with no results. You would still want to use it if you want to return a message like "no results found", of course..
Edit - Added
I think there's a problem also with the line
if(dr1["CarId"] != DBNull.Value)
You should be using if DataReader's IsDbNull() method. as in
if(dr.IsDbNull("CarId"))
Sorry I missed that the first time around.
Use dr1.Read() to check that there is a row before attempting to read values. Read gets the first row initially, and then returns subsequent rows, returning true if row available or empty/end of set.
eg.
// for reading one row
if (rd1.Read())
{
// do something with first row
}
// for reading thru multiple rows
while (rd1.Read())
{
// do something with current row
}