DataTable.SetField appears slow - c#

From performance analysis, this is very slow:
public static DataTable ReplaceNulls(DataTable table, double replacementValue = 0)
{
int r = -1;
foreach (DataRow row in table.Rows)
{
r++;
foreach (DataColumn col in table.Columns.Cast<DataColumn>().Skip(1))
{
if ((object)row[col] == DBNull.Value)
{
row.SetField(col, replacementValue);
}
}
}
return table;
}
The issue is the SetField line. Can anyone suggest a faster approach?

Related

Loop through multiple datagridview

In my windows form, I am having 10 datagridview. They are exactly same, I mean columns are exactly same.
The ids are like myGrid1,myGrid2, myGrid3, myGrid4.....myGrid10.
Now I want to loop through all datagridview at once.
string prodName = "";
for (int i = 1; i <= 10; i++)
{
foreach (DataGridViewRow dr in myGrid[i].Rows)
{
prodName += dr.Cells["ProductName"].Value
}
}
but myGrid[i] doesn't exists obviously.
I can loop each datagridview seperately but is there any easy way to do this?
Hope this helps.
foreach (Control x in this.Controls)
{
if (x is DataGridView)
{
foreach (DataGridViewRow dr in (DataGridView(x)).Rows)
{
prodName += dr.Cells["ProductName"].Value
}
}
}
or
foreach ( DataGridView dgv in this.Controls.OfType<DataGridView>())
{
foreach (DataGridViewRow dr in dgv.Rows)
{
prodName += dr.Cells["ProductName"].Value
}
}

c# Need to remove and add a row in a DataTable at a specific value

I have a DataTable dt where I have a string column Salenumber.
I need to remove the row where the Salenumber is between 1 - 5999 and move that row to DataTable dt2.
Something like this, but foreach wont work when you want to remove rows.
DataTable dt2 = new DataTable();
dt2 = CreateNewDataTable.NewDataTable();
foreach (DataRow row in dt.Rows)
{
double RowDoubleValue;
if (Double.TryParse(row["Salenumber"].ToString(), out RowDoubleValue) && RowDoubleValue >= 1.0 && RowDoubleValue <= 5999.0)
{
dt2.ImportRow(row); //Copy
dt.Rows.Remove(row); //Remove
}
}
One way to circumvent the problem that you cant modify a collection during enumeration in a foreach is to use another collection where you store the items that you want to modify, so like:
List<DataRow> rowsToRemove = new List<DataRow>();
foreach (DataRow row in dt.Rows)
{
double RowDoubleValue;
if (Double.TryParse(row["Salenumber"].ToString(), out RowDoubleValue) && RowDoubleValue >= 1.0 && RowDoubleValue <= 5999.0)
{
rowsToRemove.Add(row);
}
}
foreach(DataRow row in rowsToRemove)
{
dt2.ImportRow(row); //Copy
dt.Rows.Remove(row); //Remove
}
Another more readable and shorter way is LINQ:
var rowsToImport = from row in dt.AsEnumerable()
let salesNumDouble = row.Field<string>("Salenumber").TryGetDouble()
where salesNumDouble.HasValue
&& salesNumDouble.Value >= 1.0 && salesNumDouble.Value <= 5999.0
select row;
DataTable dt2 = rowsToImport.CopyToDataTable();
I've used this extension to try-parse a string to double?:
public static Double? TryGetDouble(this string item, IFormatProvider formatProvider = null)
{
if (formatProvider == null) formatProvider = NumberFormatInfo.CurrentInfo;
Double d = 0d;
bool success = Double.TryParse(item, NumberStyles.Any, formatProvider, out d);
if (success)
return d;
else
return null;
}
You shouldn't modify collection in foreach process, you can use DataTable.Select for simple solution
DataTable dt;
DataTable dt2;
var rows = dt.Select("Salenumber >=1 and Salenumber<5999");
foreach (var row in rows)
{
dt.Rows.Remove(row);
}
dt2.Rows.Add(rows);

Remove Item in datagridcombocell when its already use on another row C#

Hello i want to remove a item from datagridcombocell which is use on another row in same cell like this
when i select qw2120 so on next row it will not display the same item on combo cell
how its possible?
lstCombo.Clear();
foreach (DataRow dr in dt.Rows)
{
lstCombo.Add(dr.Field<string>("ProductCode").ToString());
}
foreach (DataRow dr in dt.Rows)
{
if (e.RowIndex == 0)
ProductCode.Items.Add(dr.Field<string>("ProductCode").ToString());
else
{
ProductCode.Items.Clear();
int i = 0;
foreach (var item in lstCombo)
{
if (item.ToString() == dgDetail.Rows[e.RowIndex - 1].Cells["ProductCode"].Value.ToString())
{ lstCombo.RemoveAt(i); break; }
else i++;
}
foreach (var items in lstCombo) ;
// ProductCode.
}
}
This is my code Denise

Check duplicate GridEX rows with Linq does'nt work

I have two Janus GridEXs. When an specific button is clicked, I want to add rows of first grid to another grid; but I want to check that already these rows do'nt exist in the second grid, so I used this code block with linq:
DataTable dtSelectedRows = new DataTable();
dtSelectedRows = firstGrid.GetDataSource().Clone();
foreach (GridEXRow row in rows)
{
DataRow dr = ((DataRowView)row.DataRow).Row;
if (dtSelectedRows.AsEnumerable().Count() > 0)
{
if (dtSelectedRows.AsEnumerable().Where(t => t.Field<Int32>("myColumn") == Convert.ToInt32(dr["myColumn"])).Count() == 0)
{
dtSelectedRows.ImportRow(dr);
}
}
else
dtSelectedRows.ImportRow(dr);
}
}
secondGrid.SetDataSource(dtSelectedRows);
but unfortunately it did'nt work and dtSelectedRows is always empty. So I forced to rewrite the block as:
GridEXRow[] rows = firstGrid.GetCheckedRows();
DataTable dtSelectedRows = new DataTable();
dtSelectedRows = firstGrid.GetDataSource().Clone();
foreach (GridEXRow row in rows)
{
if (row.RowType == Janus.Windows.GridEX.RowType.Record)
{
DataRow dr = ((DataRowView)row.DataRow).Row;
bool rowExists = false;
foreach (DataRow r in dtSelectedRows.Rows)
{
if (Convert.ToInt32(r["myColumn"]) == Convert.ToInt32(dr["myColumn"]))
{
rowExists = true;
break;
}
}
if (!rowExists)
dtSelectedRows.ImportRow(dr);}
}
secondGrid.SetDataSource(dtSelectedRows);
and fortunately it just worked. So how can I correct the first code block?
try this :
dtSelectedRows = firstGrid.GetDataSource().AsEnumerable().ToList();
instead of :
dtSelectedRows = firstGrid.GetDataSource().Clone();

vs2003: identify first row in DataRow[]

what is the best way to identify first row in the following code?
foreach(DataRow row in myrows)
{
if (first row )
{
...do this...
}
else
{
....process other than first rows..
}
}
You can use a boolean flag for this:
bool isFirst = true;
foreach(DataRow row in myrows)
{
if (isFirst)
{
isFirst = false;
...do this...
}
else
{
....process other than first rows..
}
}
you could just use a for loop instead
for(int i = 0; i < myrows.Count; i++)
{
DataRow row = myrows[i];
if (i == 0) { }
else { }
{
Maybe something like this?
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.Index == 0)
{
//...
}
else
{
//...
}
}
Use a int to loop through the collection.
for (int i =0; i < myDataTable.Rows.Count;i++)
{
if (i ==0)
{
//first row code here
}
else
{
//other rows here
}
}
First convert the DataRow to DataRowView:
How Can Convert DataRow to DataRowView in c#
and after that:
foreach (DataRowView rowview in DataView)
{
if (DataRowView.Table.Rows.IndexOf(rowview.Row) == 0)
{
// bla, bla, bla...
}
}

Categories