0

got an odd bug in my code and I can't see why it's behaving the way it is. I'm not the most experienced code warrior so hoping someone with a bit more experience can see why.

I'm saving a list of objects to an XML file. I pass the list of the objects to my function for saving and I have code in place to check if the object is already there and only save the object to the XML file if it doesn't exist. If I press the Save button once, it creates the file fine, and saves as expected. If I press save again it again works as expected and only new objects are saved.

The bug I have is this...

If I press the save button, say, 3 times and then delete the file, when I press save and recreate the file the list is saved 3 times. As if the previous lists are still floating around and just getting added on top of each other.

Here's my code for saving... In case it helps, my code HasElement() is an extension method for XElement, and simply returns a FirstOrDefault(). Save only happens when this is returned as null.

  public void SaveDB(List<ContactList> cl)
         {
             if (cl != null)
             {
                 if (!File.Exists(DBPath))
                 {
                     XDocument doc = new XDocument(
                         new XDeclaration("1.0", "utf-8", "yes"),
                         new XElement("Contacts")
                         );
                     doc.Save(DBPath);
                     MessageBox.Show("File Created: " + DBPath);
                 }
                 MessageBox.Show(DBPath + " already exists!");
                 XDocument Doc = XDocument.Load(DBPath);
                 List<XElement> elmAdd = new List<XElement>();
                 XElement root = Doc.Element("Contacts");

                 foreach (ContactList CL in cl)
                 { 
                    if (root.HasElement(CL.Name) == null)
                    {
                     if (CL.Selected == true)
                         {
                             XElement eName = new XElement(CL.Name, "true");
                             elmAdd.Add(eName);
                         }
                         else if (CL.Selected == false)
                         {
                             XElement eName = new XElement(CL.Name, "false");
                             elmAdd.Add(eName);
                         }
                     }
                 }


                 MessageBox.Show("Lists saved");
                 Doc.Element("Contacts").Add(elmAdd);
                 Doc.Save(DBPath);
             } // End if null
             else
             {
                 MessageBox.Show("Debug: List is empty");
             }
         } // end method
  • OT: Have the extension method "HasElement()" return a Boolean. Much clearer than: "Q:Do you have an element? A: null". – Willem van Rumpt Jul 24 '15 at 09:06
  • 1
    The easiest way to work our what's going on is to stick some break points in and step through it. There's nothing obvious, my first guess would be `cl` has more items in than you think it does. – Charles Mager Jul 24 '15 at 09:08

2 Answers2

0

Most probably the bug is out of scope of this function and somehow List with duplicate entries has been passed. You can handle such situation within yours function by Grouping using Distinct or changing yours code to append child elements one by one. But more appropriate solution will be to determine how duplicates were added to source list.

Vitaliy Kalinin
  • 1,791
  • 12
  • 20
  • It was indeed. I went back to my form where I called the save function. Where I went wrong was I had built a temporary list of objects for debugging. These objects were getting added again and again to the same list. If the file had to be recreated, and save had been pressed more than once, the list contained multiple versions of the same objects. Feeling pretty stupid right now... but thanks for the help everyone. – LeeAttewell Jul 24 '15 at 10:30
0

I have checked the code, and it seems to me, that there is something wrong in the call part. Now, when I click save, and modify the contact, contact1, contact2 to something other, then click again, the old contact values are saved with the new ones together. That's OK. When I delete the file, and click save, only the new values will be written. Less 'a' in the and of contact will be not remembered in memory.

private ContactList MyContact { get; set; } // MyContact is initialized with name contact

void Clickery(object o, RoutedEventArgs e)
{
    MyContact = new ContactList
    {
        Name = MyContact.Name + "a",
        Selected = false
    };
}

void Clicky(object o, RoutedEventArgs e)
{
    string DBPath = "somefile.txt";
    List<ContactList> cl = new List<ContactList>() { 
        MyContact,
        new ContactList { Name = "contact1", Selected = false },
        new ContactList { Name = "contact2", Selected = true } };
    if (cl != null)
    {
        if (!File.Exists(DBPath))
        {
            XDocument doc = new XDocument(
                new XDeclaration("1.0", "utf-8", "yes"),
                new XElement("Contacts")
                );
            doc.Save(DBPath);
            MessageBox.Show("File Created: " + DBPath);
        } else {
            MessageBox.Show(DBPath + " already exists!");
        }
        XDocument Doc = XDocument.Load(DBPath);
        List<XElement> elmAdd = new List<XElement>();
        XElement root = Doc.Element("Contacts");

        foreach (ContactList CL in cl)
        {
            if (root.Element(CL.Name) == null)
            {
                if (CL.Selected == true) {
                    XElement eName = new XElement(CL.Name, "true");
                    elmAdd.Add(eName);
                } else {
                    XElement eName = new XElement(CL.Name, "false");
                    elmAdd.Add(eName);
                }
            }
        }

        MessageBox.Show("Lists saved");
        Doc.Element("Contacts").Add(elmAdd);
        Doc.Save(DBPath);
    } else { // End if null
        MessageBox.Show("Debug: List is empty");
    }
} // end method

class ContactList
{
    public string Name { get; set; }
    public bool Selected { get; set; }
}
ntohl
  • 2,067
  • 1
  • 28
  • 32