Removing certain row from datatable C# - c#

I am trying to remove rows from datatable in which a certain cell is empty. I have tried using for loop but to no avail.
for (int i = dtbl.Rows.Count - 1; i >= 0; i--)
{
DataRow dr = dtbl.Rows[i];
if (dr["id"] == null)
dtbl.Rows.Remove(dr);
}
If the cell of ID column is empty, then that row should be deleted.
Any help is appreciated. Thanks in advance.

Change your test to this one.
for (int i = dtbl.Rows.Count - 1; i >= 0; i--)
{
DataRow dr = dtbl.Rows[i];
if (dr.IsNull("id"))
dtbl.Rows.Remove(dr);
}
See docs: DataRow.IsNull
or you can use a check against the special field DbValue.Null
if (dr["id"] == DbNull.Value)
Another approach is this one
for (int i = dtbl.Rows.Count - 1; i >= 0; i--)
{
DataRow dr = dtbl.Rows[i];
if (dr.IsNull("id"))
dr.Delete();
}
dtbl.AcceptChanges();
this last one just marks the row for deletion, but the row remains in the table until you call AcceptChanges. (So this approach is suitable for a foreach loop)
Calling DataRow.Delete is the preferred way to work if you plan to update the real database table at later time (for example when you want your user delete many rows from a bound grid and then make a single update to the database only if the user clicks on a Save button).

You could use linq to select those not null
dtbl = dtbl.AsEnumerable()
.Where(r => r.Field<string>("id") != null)
.CopyToDataTable();
Might need the type, specify that nullable type to compare row.Field<int?>("id").HasValue

Related

How can I send the selected rows of a DataGridView to a Datatable, BUT ignoring the first column?

Hellou to everyone.
I would love the assistance from you guys.
My problem is like this:
I have this datagridview which I fill using datasource (a query to a db table). I only created manually one column which contain a checkbox. When the binding is complete I can click the checkboxes to select the row and I can select multiples rows this way.
I want to put the selected rows into a datatable (so I can read it and do some sql queries with the information on it) BUT when I read the selected rows to put them inside a datatable I need to skip the checkbox column (the first one).
How can I achieve this?
Okay, for future reference, I'm gonna post here how I fixed it.
DataTable dt = new DataTable();
if (dgvPedidos.SelectedRows.Count > 0)
{
foreach (DataGridViewColumn column in dgvPedidos.Columns)
dt.Columns.Add();
int i = 0;
foreach(DataGridViewRow row in dgvPedidos.Rows)
{
if (Convert.ToBoolean(dgvPedidos.Rows[i].Cells["chkPedido"].Value) == true)
{
dt.Rows.Add();
dt.Rows[i][1] = row.Cells[1].Value.ToString();
dt.Rows[i][2] = row.Cells[2].Value.ToString();
dt.Rows[i][3] = row.Cells[3].Value.ToString();
dt.Rows[i][4] = row.Cells[4].Value.ToString();
dt.Rows[i][5] = row.Cells[5].Value.ToString();
dt.Rows[i][6] = row.Cells[6].Value.ToString();
dt.Rows[i][7] = row.Cells[7].Value.ToString();
dt.Rows[i][8] = row.Cells[8].Value.ToString();
dt.Rows[i][9] = row.Cells[9].Value.ToString();
i++;
}
}
dt.Columns.RemoveAt(0);

How to copy specific rows from DataTable to another one

I want to copy some rows of data table, to another one. I tried this code :
DataTable Result = new DataTable();
for(int i = 5; i < PageSize && i < TransactionDataTable.Rows.Count ; i++)
{
DataRow dr = (DataRow)TransactionDataTable.Rows[i];
Result.ImportRow(dr);
}
string MobileNumber = TransactionDataTable.Rows[0]["MobileRegistration_MobileNumber"].ToString();
string MobileNumber2 = Result.Rows[0]["MobileRegistration_MobileNumber"].ToString();
TransactionDataTable is a dataTable with more than 1000 rows.
in above code, MobileNumber has proper vallue, but MobileNumber2 dosent have.
I got this error in last line ( in assigning MobileNumber2 value) :
Additional information: Column 'MobileRegistration_MobileNumber' does not belong to table .
It seems that the rows didnt copy properly, in Result dataTable.
whats the wrong with this code?
and I tried Result.Rows.Add(dr); instead of Result.ImportRow(dr);
but an exception throw with this information:
This row already belongs to another table.
Thanks for any helping...
You are making new datatable Result without any column. So, make sure you are bringing all columns from the table which you are going to copy.
In your case, you can clone the TransactionDataTable and then import the row.
The updated copy implementation will be like this :
DataTable Result = TransactionDataTable.Clone();
for(int i = 5; i < PageSize && i < TransactionDataTable.Rows.Count ; i++)
{
DataRow dr = (DataRow)TransactionDataTable.Rows[i];
Result.ImportRow(dr);
}
string MobileNumber = TransactionDataTable.Rows[0]["MobileRegistration_MobileNumber"].ToString();
string MobileNumber2 = Result.Rows[0]["MobileRegistration_MobileNumber"].ToString();

Check whether it is deleting last row with specified value in column

I have a button that deletes rows from a DataGrid; one of the columns is the admin column. I need the program to check whether the row (or rows, since it can delete multiple rows) that is being deleted is the last one with Admin = true, since deleting the last administrator renders this table unaccessible.
The code for deleting rows is this:
connection.Open();
List<DataRow> theRows = new List<DataRow>();
for (int i = 0; i < funcDataGrid.SelectedItems.Count; ++i)
{
Object o = funcDataGrid.SelectedItems[i];
if (o != CollectionView.NewItemPlaceholder)
{
DataRowView r = (DataRowView)o;
theRows.Add(r.Row);
}
}
foreach (DataRow r in theRows)
{
string a = r.Field<string>("usernameFunc");
cmdSel = new MySqlCommand("DELETE FROM usersFunc WHERE usernameFunc='"
+ a + "'", connection);
cmdSel.ExecuteNonQuery();
int k = ds.Tables["funcionarios"].Rows.IndexOf(r);
ds.Tables[0].Rows[k].Delete();
}
connection.Close();
Keep in mind it's deleting from two joined tables, so I couldn't delete rows the usual way.
You could have a variable (static or not, depending on how you implemented your class) called ActiveAdmins. Upon loading of your Datagrid, you could easily query your DB and get the number of admins.
I'll assume you have a boolean column IsAdmin on your objects.
in your foreach loop, add something like:
if (r.Field<string>("IsAdmin"))
if (`ActiveAdmins` <= 1)
continue;
This way, whenever you're deleting, if it's the last admin stading, it'll just go to the next row, leaving your last admin in the table.

Performance of setting DataRow values in a large DataTable

I have a large DataTable - around 15000 rows and 100 columns - and I need to set the values for some of the columns in every row.
// Creating the DataTable
DataTable dt = new DataTable();
for (int i = 0; i < COLS_NUM; i++)
{
dt.Columns.Add("COL" + i);
}
for (int i = 0; i < ROWS_NUM; i++)
{
dt.Rows.Add(dt.NewRow());
}
// Setting several values in every row
Stopwatch sw2 = new Stopwatch();
sw2.Start();
foreach (DataRow row in dt.Rows)
{
for (int j = 0; j < 15; j++)
{
row["Col" + j] = 5;
}
}
sw2.Stop();
The measured time above is about 4.5 seconds. Is there any simple way to improve this?
Before you populate the data, call the BeginLoadData() method on the DataTable. When you have finished loading the data, call EndLoadData(). This turns off all notifications, index maintenance, and constraints, which will improve performance.
As an alternative, call BeginEdit() before updating each row, and EndEdit() when the editing for that row is complete.
Here is a link with more information on improving DataSet performance:
http://www.softwire.com/blog/2011/08/04/dataset-performance-in-net-web-applications/
One improvement that I can think of is editing columns by their indices, rather than their names.
foreach (DataRow row in dt.Rows)
{
for (int j = 0; j < 15; j++)
{
row[j] = 5;
}
}
With an empirical test, your method seems to run in ~1500 milliseconds on my computer, and this index based version runs in ~1100 milliseconds.
Also, see Marc's answer in this post:
Set value for all rows in a datatable without for loop
this depends on your business logic which is not clear in your question, however, If you want to set the values for some of the columns in every row, try the following,
Create a separated temp column(s), you might create it in the same
loop when creating the original data table
Fill the new values into this column,
delete the old column and insert the new one in its place instead.
This solution will be logical if you can expect the new values or if you have the same value for all rows (like in your example) or if you have some kind of repeat, in that case adding a new column with loaded will be much more faster than looping all rows.

Move row to top in data table c#

I have a data table in which if the Addresses match move one of the rows to the top of the data table. I am using the following code but it doesnt work. Any idea how to achieve this. The data in the data table is imported from an excel file. I have tried the same if statement in GridView to highlight the duplicates and that works but I also want to move them to the top because the data has more than 1000 rows and its hard to move up and down again and again to check for the highlighted row.
for (int row = 1; row < dtf1.Rows.Count; row++)
{
for (int rowinner = 1; rowinner < dtf1.Rows.Count; rowinner++)
{
if (rowinner != row)
{
if (dtf1.Rows[row][addresscolno] == dtf1.Rows[rowinner][addresscolno].ToString())
{
DataRow newrow = dtf1.Rows[row];
dtf1.Rows.RemoveAt(row);
dtf1.AcceptChanges();
dtf1.Rows.InsertAt(newrow, 1);
dtf1.AcceptChanges();
GridView1.DataSource = dtf1;
GridView1.DataBind();
}
}
}
}
So you want to reorder the DataTable. The row with a given address should be on the top. You can use Linq-To-DataSet to order the rows and CopyToDataTable to create a new DataTable with the new order:
// assuming the address is a string in a variable address, to simplify matters
DataTable tblOrdered = dtf1.AsEnumerable()
.OrderByDescending(r => r.Field<string>("addresscolno") == address)
.ThenBy(r => r.Field<string>("addresscolno"))
.CopyToDataTable();
Then you can use that as DataSource for your GridView.
Edit: Give also DataTable.Rows.InsertAt a try.
dtf1.Rows.InsertAt(dtf1.Rows[rowinner], 0);

Categories