locked
Save Conflict error RRS feed

  • Question

  • Hi, I have this error somewhere here, any idea why that happen?

    Exceptions: Save Conflict.

    Your changes conflict with those made concurrently by another user. If you want your changes to be applied, click Back in your Web browser, refresh the page, and resubmit your changes.

    When a list item is deleted what happen to the value "i", do I have to  "i++;"? Is that because the index got screwed up. Please advice. Your help would be greatly appreciated.

              try
                    {
                        using (SPSite site = new SPSite(AppSettings.ServerURL))
                        {
                            using (SPWeb web = site.OpenWeb())
                            {
                                SPList list = web.Lists[AppSettings.TimeOffCalendar];
                                for (int i = list.Items.Count - 1; i >= 0; i--)
                                {
                                    if (list.Items[i]["FormId"].ToString() == formId)
                                    {
                                        list.Items.Delete(i);
                                    }
                                }
                                list.Update();
                            }
                        }
                    }

    Tuesday, February 7, 2012 6:24 PM

Answers

  • You cannot modify the collection while you are iterating through it. When you find a match add the item's ID to a List<int>. Then iterate through this List<int> and call list.GetItemByID and delete it.

    Blog | SharePoint Field Notes Dev Tool | ClassMaster

    • Proposed as answer by Jeffrey Zeeman Tuesday, February 7, 2012 6:43 PM
    • Marked as answer by wkpli Monday, February 13, 2012 5:03 PM
    Tuesday, February 7, 2012 6:36 PM
  • http://www.praveenmodi.com/programmatically-delete-all-items-sharepoint-list/

    You can get the IDs of the elements based on your condition and store them in an array and do list. Now do List.GetItemById(id).Delete

    You might also want to consider using SPListItem.Recycle to delete and send the item to recycle bin.

    • Marked as answer by wkpli Monday, February 13, 2012 5:04 PM
    Tuesday, February 7, 2012 6:40 PM

All replies

  • You cannot modify the collection while you are iterating through it. When you find a match add the item's ID to a List<int>. Then iterate through this List<int> and call list.GetItemByID and delete it.

    Blog | SharePoint Field Notes Dev Tool | ClassMaster

    • Proposed as answer by Jeffrey Zeeman Tuesday, February 7, 2012 6:43 PM
    • Marked as answer by wkpli Monday, February 13, 2012 5:03 PM
    Tuesday, February 7, 2012 6:36 PM
  • Try like

    try
                     {
                         using (SPSite site = new SPSite(AppSettings.ServerURL))
                         {
                             using (SPWeb web = site.OpenWeb())
                             {
                                 SPList list = web.Lists[AppSettings.TimeOffCalendar];
    
                                  web.AllowUnsafeUpdates = true;
                                 for (int i = list.Items.Count - 1; i >= 0; i--)
                                 {
                                     if (list.Items[i]["FormId"].ToString() == formId)
                                     {
                                         list.Items.Delete(i);
                                     }
                                 }
                                 web.AllowUnsafeUpdates = false;
                             }
                         }
                     }

    Tuesday, February 7, 2012 6:37 PM
  • http://www.praveenmodi.com/programmatically-delete-all-items-sharepoint-list/

    You can get the IDs of the elements based on your condition and store them in an array and do list. Now do List.GetItemById(id).Delete

    You might also want to consider using SPListItem.Recycle to delete and send the item to recycle bin.

    • Marked as answer by wkpli Monday, February 13, 2012 5:04 PM
    Tuesday, February 7, 2012 6:40 PM
  • Your using a for next loop to iterate through items and delete them, but you are using the i iterator for the index, this won't work as is,

    When you do

    item[i].Delete(), you are removing an element from the collection which is going to change the value returned from list.Items.Count

    To get that to work, first do this

    int count = list.Items.Count;

    then, change your loop,

    int deleteIndex = 0;

                                 for (int i = 0;i <= count; ++i)
                                 {
                                     if (list.Items[deleteIndex]["FormId"].ToString() == formId)
                                     {
                                         list.Items.Delete(deleteIndex);
                                     }				 else  				 {					++deleteIndex; 				  }
                                 }

    When you remove an item from the collection the next item will slide up to the index of the item you just deleted.  For that matter, in the modification above when an Item is deleted I don't increment the deleteIndex, if the item is not deleted the item stays where it is and we want to check the next item, so increment deleteIndex by 1.

    Now if your using a foreach loop, then you cannot modify the collection being looped through as it will blow up the IEnumerable and IEnumerator interfaces on the collection being looped through (by design).

    Edit:  This could also cause some threading issues.  E.g. Imagine code in another thread deletes an item you are about to iterate to while your code is in the middle of it's iteration, an unmost untraceable, undebugable problem will arise in such a situation because it will appear that the iteration logic is off by 1 on the index, when in actuality it was correct but another thread intercepted an item you were about to iterate through.

    In short, it's bad to manipulate a collection while iterating through it, that's why the foreach operator doesn't allow it.  What you could do is store all of the items to a List<SPListItem> then iterate through those and delete them from list.Items, but check that they haven't already been deleted first, should be thread safe for the most part.


    My Blog: http://www.thesug.org/Blogs/ryan_mann1/default.aspx Website: Under Construction


    • Edited by Ryan T Mann Wednesday, February 8, 2012 4:57 PM
    Tuesday, February 7, 2012 10:34 PM
  • GetItemById works perfectly. Thanks
    Monday, February 13, 2012 5:04 PM
  •    I get the save conflict error in the below code that i use.As per the logs that i put across every step i notice that after deleting the folder only it is throwing the save conflict error.

      //If a folder with the same name already exists,delete the exisitng folder
                        if (folder.Exists)
                        {
                            SPFileCollection fileCollection = folder.Files;

                            //Get the list of files inside the existing pack folder and verify if any of the files
                            //are checked out or locked by any user.If the file is checked out,undocheckout is given and
                            //then the entire Pack Folder is deleted


                            for (int fileIndex = 0; fileIndex < fileCollection.Count; fileIndex++)
                            {
                                if (fileCollection[fileIndex].CheckedOutBy != null)
                                {
                                    fileCollection[fileIndex].UndoCheckOut();

                                }
                            }

                            _MyDocLibrary.Update();
                            _MyWeb.Update();

                            //Delete Pack Folder
                            folder.Delete();

                            _MyDocLibrary.Update();
                            _MyWeb.Update();

                        }


                        //Now add a folder with the same pack name

                        _MyFolders.Add(SharepointUrl + DocLib + "/" + LoanID + "/" + PackName + "-" + PackNo);

                        _MyDocLibrary.Update();
                        _MyWeb.Update();

                        _MyWeb.AllowUnsafeUpdates = false;
                        _MySite.AllowUnsafeUpdates = false;

                        //Perform Cleanup
                        _MyWeb.Dispose();
                        _MySite.Dispose();

    Wednesday, July 25, 2012 12:31 PM