Deleting data in dataset

D

David

Hi all,

Using C# 1.1

I have a dataset loaded from an XML file. The idea being that if the app (a
winform app that relies on a webservice) is offline, then I save data
locally in XML and update the web service later.

So, when I update, I have something like...

DataSet siteLinks = new DataSet();
siteLinks.ReadXml(WorkingDirectory + @"\temp\SaveLinks.xml");

// Upload Link Data.
foreach (DataRow dr in siteLinks.Tables[0].Rows)
{
try
{
if (uploaddatatowebservice) // Saves data into webservice and
returns boolean
{
// Remove the row once it has been processed.
dr.Delete();
}
else
{
MessageBox.Show("There was a problem saving the link. If problems
persist, please contact the administrator.");
}
}
catch(Exception ex)
{
string exc = ex.Message;
}
}

if (siteLinks.HasChanges())
{
siteLinks.AcceptChanges();
}


However, I get a problem... dr is the datarow from the dataset. I try and
delete the datarow (which seems to work, though is not actually deleted from
the XML at this point) but on the next iteration of the loop, I get a
System.InvalidOperationException Collection was modified; enumeration
operation may not execute.

What am I doing wrong?

Also, will what I have here actually save the changes back into the XML? If
not, what am I missing?

Thanks.
--
Best regards,
Dave Colliver.
http://www.LincolnFOCUS.com
~~
http://www.FOCUSPortals.com - Local franchises available
 
C

ClayB

The error message suggests you are trying to modify the collection
through which you are iterating. And since you are deleting datarows
from siteLinks.Tables[0].Rows, this is what you are doing... changing
the iteration set.

One solution is to not directly delete the datarows during this first
pass. Instead, collect them in an ArrayList. Then after your first
pass, iterate through this ArrayList which holds the DataRows to be
deleted, and delete them in this second loop.

===============
Clay Burch
Syncufsion, Inc.
 
G

Guest

As for the exception switch from a foreach to a for where you start at the
last element and work forward or when you delete a record you decrement the
counter. GetEnumerator does not support deletes during the iteration.
 
G

Guest

You never serialized back to the XML. (siteLinks.WriteXml(WorkingDirectory +
@"\temp\SaveLinks.xml");)

You accept changes which will be disposed once the DataSet object goes out
scope.
 
D

David

Thanks Josh,

I have done a reverse for loop and that now does not error... However, I do
have another problem... My code now looks like...


for (int Count = siteLinks.Tables[0].Rows.Count-1; Count >= 0; Count --)
{
DataRow dr = siteLinks.Tables[0].Rows[Count];
try
{
if (uploadedtowebservice)
{
// Remove the row once it has been processed.
dr.Delete();
}
}
catch(Exception ex)
{
string exc = ex.Message;
}
}

if (siteLinks.HasChanges())
{
siteLinks.AcceptChanges();
}

but the siteLinks.HasChanges is not set for some reason.

Once I have deleted the row from the datarow, I need to save the changes, so
that I don't end up reading it again the next time I run through the loop.

Thanks.
--
Best regards,
Dave Colliver.
http://www.AshfieldFOCUS.com
~~
http://www.FOCUSPortals.com - Local franchises available
Josh said:
As for the exception switch from a foreach to a for where you start at the
last element and work forward or when you delete a record you decrement
the
counter. GetEnumerator does not support deletes during the iteration.

ClayB said:
The error message suggests you are trying to modify the collection
through which you are iterating. And since you are deleting datarows
from siteLinks.Tables[0].Rows, this is what you are doing... changing
the iteration set.

One solution is to not directly delete the datarows during this first
pass. Instead, collect them in an ArrayList. Then after your first
pass, iterate through this ArrayList which holds the DataRows to be
deleted, and delete them in this second loop.

===============
Clay Burch
Syncufsion, Inc.
 
G

Guest

David,

I think that the problem is that you are trying to delete a row while you
are still inside of the foreach loop. The safer method of doing this would
seem to me to be to build a collection of rows that you want to delete and
delete them after the ds has been iterated through.


The other option would be to iterate through the index of the rows in
reverse order with a regular for next loop rather than a foreach.
 
D

David

Thank you. I will give this a go. I didn't know if the accept changes would
have done this implicitly. Obviously not.


--
Best regards,
Dave Colliver.
http://www.AshfieldFOCUS.com
~~
http://www.FOCUSPortals.com - Local franchises available
Josh said:
You never serialized back to the XML. (siteLinks.WriteXml(WorkingDirectory
+
@"\temp\SaveLinks.xml");)

You accept changes which will be disposed once the DataSet object goes out
scope.

David said:
Hi all,

Using C# 1.1

I have a dataset loaded from an XML file. The idea being that if the app
(a
winform app that relies on a webservice) is offline, then I save data
locally in XML and update the web service later.

So, when I update, I have something like...

DataSet siteLinks = new DataSet();
siteLinks.ReadXml(WorkingDirectory + @"\temp\SaveLinks.xml");

// Upload Link Data.
foreach (DataRow dr in siteLinks.Tables[0].Rows)
{
try
{
if (uploaddatatowebservice) // Saves data into webservice and
returns boolean
{
// Remove the row once it has been processed.
dr.Delete();
}
else
{
MessageBox.Show("There was a problem saving the link. If problems
persist, please contact the administrator.");
}
}
catch(Exception ex)
{
string exc = ex.Message;
}
}

if (siteLinks.HasChanges())
{
siteLinks.AcceptChanges();
}


However, I get a problem... dr is the datarow from the dataset. I try and
delete the datarow (which seems to work, though is not actually deleted
from
the XML at this point) but on the next iteration of the loop, I get a
System.InvalidOperationException Collection was modified; enumeration
operation may not execute.

What am I doing wrong?

Also, will what I have here actually save the changes back into the XML?
If
not, what am I missing?

Thanks.
--
Best regards,
Dave Colliver.
http://www.LincolnFOCUS.com
~~
http://www.FOCUSPortals.com - Local franchises available
 
G

Guest

AcceptChanges only tracks changes to a row. If you delete a row there is
nothing to track changes on thus nothing to accept.

This is an example why they require you to write back to the source
explicitly. There are scenarios where you may not want the DataSet to auto
write back to the Data Source. You would call WriteXML in this particulair
case.

Hope this all makes sense.

David said:
Thanks Josh,

I have done a reverse for loop and that now does not error... However, I do
have another problem... My code now looks like...


for (int Count = siteLinks.Tables[0].Rows.Count-1; Count >= 0; Count --)
{
DataRow dr = siteLinks.Tables[0].Rows[Count];
try
{
if (uploadedtowebservice)
{
// Remove the row once it has been processed.
dr.Delete();
}
}
catch(Exception ex)
{
string exc = ex.Message;
}
}

if (siteLinks.HasChanges())
{
siteLinks.AcceptChanges();
}

but the siteLinks.HasChanges is not set for some reason.

Once I have deleted the row from the datarow, I need to save the changes, so
that I don't end up reading it again the next time I run through the loop.

Thanks.
--
Best regards,
Dave Colliver.
http://www.AshfieldFOCUS.com
~~
http://www.FOCUSPortals.com - Local franchises available
Josh said:
As for the exception switch from a foreach to a for where you start at the
last element and work forward or when you delete a record you decrement
the
counter. GetEnumerator does not support deletes during the iteration.

ClayB said:
The error message suggests you are trying to modify the collection
through which you are iterating. And since you are deleting datarows
from siteLinks.Tables[0].Rows, this is what you are doing... changing
the iteration set.

One solution is to not directly delete the datarows during this first
pass. Instead, collect them in an ArrayList. Then after your first
pass, iterate through this ArrayList which holds the DataRows to be
deleted, and delete them in this second loop.

===============
Clay Burch
Syncufsion, Inc.
 
G

Guest

Yeah the limatation here is GetEnumerator calls. foreach relies on the
IEnumerable interface function GetEnumerator. This method will throw an
exception if the count of items changes in the underlying collection.

The most efficent option:
-Use a for loop which updates on a delete the counter state. If your moving
forwards. You should decrement the counter after you delete. It you moving
backwards you should increment the counter after a delete.

What code smith is proposing is doable. It is just not the most efficent.

Codesmith said:
David,

I think that the problem is that you are trying to delete a row while you
are still inside of the foreach loop. The safer method of doing this would
seem to me to be to build a collection of rows that you want to delete and
delete them after the ds has been iterated through.


The other option would be to iterate through the index of the rows in
reverse order with a regular for next loop rather than a foreach.

David said:
Hi all,

Using C# 1.1

I have a dataset loaded from an XML file. The idea being that if the app (a
winform app that relies on a webservice) is offline, then I save data
locally in XML and update the web service later.

So, when I update, I have something like...

DataSet siteLinks = new DataSet();
siteLinks.ReadXml(WorkingDirectory + @"\temp\SaveLinks.xml");

// Upload Link Data.
foreach (DataRow dr in siteLinks.Tables[0].Rows)
{
try
{
if (uploaddatatowebservice) // Saves data into webservice and
returns boolean
{
// Remove the row once it has been processed.
dr.Delete();
}
else
{
MessageBox.Show("There was a problem saving the link. If problems
persist, please contact the administrator.");
}
}
catch(Exception ex)
{
string exc = ex.Message;
}
}

if (siteLinks.HasChanges())
{
siteLinks.AcceptChanges();
}


However, I get a problem... dr is the datarow from the dataset. I try and
delete the datarow (which seems to work, though is not actually deleted from
the XML at this point) but on the next iteration of the loop, I get a
System.InvalidOperationException Collection was modified; enumeration
operation may not execute.

What am I doing wrong?

Also, will what I have here actually save the changes back into the XML? If
not, what am I missing?

Thanks.
--
Best regards,
Dave Colliver.
http://www.LincolnFOCUS.com
~~
http://www.FOCUSPortals.com - Local franchises available
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top