Error when trying to duplicate rows in DataTable in c# - c#

I have an existing datatable called _longDataTable containing data. Now, I want to duplicate each row and in each duplicate of the row, I want to set only the value in the SheetCode column according to a value from a different datatable called values, see code below. For example, the values datatable contains 1, 2 and 3, then I want each row of _longDataTable to be duplicated three times and in each of the duplicated rows, I want the Sheet Code column to have values 1, 2 and 3 respectively. My code now looks like below:
foreach (DataRow sheets in _longDataTable.Rows)
{
for(int k = 0; k < number_of_sheets; k++)
{
var newRowSheets = _longDataTable.NewRow();
newRowSheets.ItemArray = sheets.ItemArray;
newRowSheets["SheetCode"] = values.Rows[k]["Sheet Code"];
//add edited row to long datatable
_longDataTable.Rows.Add(newRowSheets);
}
}
However, I get the following error:
Collection was modified; enumeration operation might not execute.
Does anyone know where this error comes from and how to solve my problem?

you get enumeration error because you are iterating through a collection which is changing in the loop(new rows added to it),
as you said in the comment, you get out of memory exception because you are iterating on the _longDataTable, then you add rows to it, the iteration never reach to end and you will get out of memory exception.
I assume this can help you:
//assume _longDataTable has two columns : column1 and SheetCode
var _longDataTable = new DataTable();
var duplicatedData = new DataTable();
duplicatedData.Columns.Add("Column1");
duplicatedData.Columns.Add("SheetCode");
foreach (DataRow sheets in _longDataTable.Rows)
{
for (int k = 0; k < number_of_sheets; k++)
{
var newRowSheets = duplicatedData.NewRow();
newRowSheets.ItemArray = sheets.ItemArray;
newRowSheets["SheetCode"] = values.Rows[k]["Sheet Code"];
newRowSheets["Column1"] = "anything";
//add edited row to long datatable
duplicatedData.Rows.Add(newRowSheets);
}
}
_longDataTable.Merge(duplicatedData);
do not modify _longDataTable, add rows to the temp table (with the same schema) and after the iteration merge two data tables.

Related

How would I filter this dataset?

I have a dataset that looks like the image. I'm trying to filter by table and get all the columns next to it and compare them against other datasets
This dataset has tables named table 1 and table 2 and when they're selected they look like the picture below. It shows the columns and I need to compare those columns against the rows from the matching table in the first dataset
I've looked at dataview but that would be a lot of work and I'm very inexperienced. I'm trying to find a way to implement a foreach loop that'll get the name of the table in the first dataset and then compare the rows in it against the columns inside the datatable in the second dataset that matched the table name from the first dataset.
Without knowing more about these DataSets (like do they have primary keys, the data types of the columns, the number of rows in each table, etc), I can only provide limited help. The following example tries to be as general as possible and avoid some basic problems:
DataSet ds1 = <<fetch dataset1>>;
DataSet ds2 = <<fetch dataset2>>;
foreach (DataTable tbl1 in ds1.Tables)
{
if (ds2.Tables.Contains(tbl1.TableName))
{
DataTable tbl2 = ds2.Tables[tbl1.TableName];
List<string> commonColumnNames = new List<string>(tbl1.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Intersect(tbl2.Columns.Cast<DataColumn>().Select(c => c.ColumnName)));
int maxRows = Math.Min(tbl1.Rows.Count, tbl2.Rows.Count);
for (int r = 0; r <= maxRows; r++)
{
foreach (string colName in commonColumnNames)
{
if (tbl1.Rows[r][colName] != tbl2.Rows[r][colName])
{
// Different value
}
}
}
}
}
Update 1: I've added comments to the following example to explain step-by-step what this code is doing. As I try to say before, since I didn't know much about your data, I had to put in extra code. This extra code is for things like: 'Does the table ABC exist in both DataSets?', 'Do the two tables have the same columns in them?', 'Do the tables have the same number of rows in them?'. Your original question did not have this information, so I made this code a little more robust to handle those unknowns.
DataSet ds1 = <<fetch dataset1>>;
DataSet ds2 = <<fetch dataset2>>;
// Loop through all of the tables in the 1st DataSet
foreach (DataTable tbl1 in ds1.Tables)
{
// If the 2nd DataSet has a table with same name as the one from the 1st DataSet
if (ds2.Tables.Contains(tbl1.TableName))
{
DataTable tbl2 = ds2.Tables[tbl1.TableName];
// Create a list of column names that the two tables have in common.
// We will only compare the values in these two tables, in this set of matching column names.
List<string> commonColumnNames = new List<string>(tbl1.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Intersect(tbl2.Columns.Cast<DataColumn>().Select(c => c.ColumnName)));
// Before we start comparing the rows in the two tables, find out which one has the fewer number of rows in it.
int maxRows = Math.Min(tbl1.Rows.Count, tbl2.Rows.Count);
// If the tables have a different number of rows, then we will only compare the set of rows numbered 0-to-MinRowCount
for (int r = 0; r <= maxRows; r++)
{
// For each row, compare the values of common columns
foreach (string colName in commonColumnNames)
{
if (tbl1.Rows[r][colName] != tbl2.Rows[r][colName])
{
// Different value
}
}
}
}
}

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();

dataGridView population from dataSet

I cannot get my dataGridView to update with all the tables in the dataSet. I just get one row in the dataGridView after I try to populate it.
I call this to fill my dataSet:
DataTable table = new DataTable(DateTime.Now.ToString());
table.Columns.Add("c1");
table.Columns.Add("c2");
table.Columns.Add("c3");
table.Columns.Add("c4");
table.Columns.Add("c5");
table.Columns.Add("c6");
table.Columns.Add("c7");
table.Rows.Add("s1", "s2", "s3", "s4", "s5", "s6", "s7");
dataSet1.Tables.Add(table);
dataSet1.WriteXml("MyData.xml");
The data is written fine, but if I try to read it with this I only get one row populated, even if there's multiple entries in the dataSet.
dataSet1.ReadXml("MyData.xml");
MessageBox.Show((dataSet1.GetXml()));
I get the message with the data in the correct format, with the correct number of entries.
dataGridView2.AutoGenerateColumns = true;
int i2 = 0;
while (i2 < dataSet1.Tables.Count)
{
dataGridView2.DataSource = dataSet1.Tables[i2];
i2++;
}
After this it will only show one row and not the amount of tables. The dataSet1.Tables.Count >= 2, but still only get 1 row.
Edit: It seems that each time I call this line:
dataGridView2.DataSource = dataSet1.Tables[i2];
It is deleting the previous row. Is there any way to append the row instead?
You only created one table in the data set, so your while statement only executes once:
while (i2 < dataSet1.Tables.Count)
{
...
}
Count = 1 (number of tables) because you only called dataSet1.Tables.Add(table); one time.
dataSet1.WriteXml("MyData.xml") is only writing out the schema for that single table. So reading it back in will only read back in a single table's worth of schema.
The following code appears to count the number of tables in the dataset:
while (i2 < dataSet1.Tables.Count)
Try pointing this to the table:
dataSet1.Tables["Yourtable"].Count

Spit DataTable into two by Rows

I have one asp.net datatable and I want to databind into two asp.net datalists, so I though to slice the datatable rows in two datatables both the same size if even .
Use the Take LINQ extension method to specify how many items to use.
And the Skip to jump over if needed.
var half = myList.Take(myList.Count / 2);
If you are slicing by rows, you can simply create a copy of your original data table, find a suitable half way point, and just import the rows into the copy, while deleting them from the original.
Something like the following should work:
DataTable originalTable = new DataTable();
//Load the data into your original table or wherever you get your original table from
DataTable otherTable = originalTable.Copy(); //Copys the table structure only - no data
int rowCount = originalTable.Rows.Count;
int wayPoint = rowCount / 2; //NB integer division rounds down towards 0
for(int i = 0; i <= wayPoint; i++)
{
otherTable.ImportRow(originalTable.Rows[i]); //Imports (copies) the row from the original table to the new one
originalTable.Rows[i].Delete(); //Marks row for deletion
}
originalTable.AcceptChanges(); //Removes the rows we marked for deletion

How can I delete and rewrite rows in a datatable and write them back from a datarow[] array in a different order?

I tried saving the datatable rows to a datarow[] array then deleting the datatable rows and rewrite them to the datatable from the datarow[] array in a different order. But when I delete them from the datatable I can't access them from the datarow[] array.
I don't know if I'm doing this correct or if im totally off base but I'm in desperate need of help.
This is what I'm trying to do:
I have a datatable with 8 rows.
I want to be able to somehow loop thru the 8 rows and reorder them based on certain criterias.
For example, my rows have an Invoice number, line number, and Part number as the key fields. Depending on the criteria, I may need rows 6,7,8 to be in the beginning as rows 1,2,3 and shift the rest down.
If anyone has an Idea please reply....this is an urgent issue.
thank you,
Sam
Use the DataView to view the rows because it can be sorted like this.
dataTable.DefaultView.Sort = "columnNameA, columnNameB desc";
Then bind the list, whatever you're using, to the DataView.
Oh and here's some documentation on the Sort property.
If you take a DataRow:
var dr = table.Rows[0];
and then delete the row from the table, dr will also be deleted. It's the same row. That explains your problem.
As for the solution, don't reorder rows in a DataTable. Instead, add another column called RowOrder, modify it to change the order, and then sort the DataTable based on that column, as #mperrenoud03 has shown you:
table.DefaultView.Sort = "RowOrder";
and use the default view.
You can try with something like this:
DataTable table = new DataTable();
table.Columns.Add("Invoice", typeof(string));
table.Columns.Add("Line", typeof(int));
table.Columns.Add("Part", typeof(string));
for (int i = 1; i <= 9; i++)
table.Rows.Add("Invoice " + i, i, "Part " + i);
//reorder them:
int[] orders = { 6, 7, 8, 1, 2, 3, 4, 5 };
DataTable table2 = table.Clone();
DataRow row;
for (int i = 0; i < orders.Length; i++)
{
row = table2.NewRow();
row["Invoice"] = table.Rows[orders[i]]["Invoice"];
row["Line"] = table.Rows[orders[i]]["Line"];
row["Part"] = table.Rows[orders[i]]["Part"];
table2.Rows.Add(row);
}

Categories