-1

I'm using XML to mock up a database and, when loading it with dummy data, I keep getting an error telling me that there are multiple root elements. Upon opening the file I can confirm that multiple root elements are being written to the file, but outside of simply calling the process synchronously, nothing I've done seems to prevent it from doing so.

Here's an example of my code:

// Check to see if the file is available. If it is, parse it. Otherwise create
// a new root element. Done in the constructor since the XElement is used in
// multiple locations.
public CourseXmlWriter()
{
    if (!File.Exists(Settings.Default.DataDirectory + Settings.Default.AltDb))
    {
        _courses = new XElement("Courses");
    }
    else
    {
        var attempts = 0;

        while (attempts < MaxAttempts)
        {
            try
            {
                using (var stream = new FileStream(_dataFile, 
                 FileMode.OpenOrCreate, FileAccess.Read, FileShare.None))
                {
                    _courses = XElement.Load(stream);
                }

                break;
            }
            catch (IOException)
            {
                Thread.Sleep(1000);
                attempts++;
            }

        }
    }
}

For the initial load, I'm only trying to read the file so that it can be parsed, so I'm restricting its access. I'm also making sure that no one can access it while I'm parsing it in. I'll try this for a certain amount of time before moving on and refusing the request altogether.

Then, when attempting to write the information to a file I'm doing the following:

var attempts = 0;

while (attempts < MaxAttempts)
{
    try
    {
        using (var stream = new FileStream(_dataFile,
          FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
        {
            _courses.Save(stream);
        }

        break;
    }
    catch (IOException)
    {
        attempts++;
        Thread.Sleep(1000);
    }
}

Again, this is running asynchronously and I can successfully write a few (15-150) records before it crashes with the There are multiple root elements. Line 15, position 6. Where position and line are variable.

Here are the asynchronous calls and callback:

The calls:

for (var i = 0; i < coursesToGenerate; i++)
{
    var request = new CreateCourseRequest
    {
        Description = Path.GetRandomFileName().Replace(".", ""),
        Name = Path.GetRandomFileName().Replace(".", "")
    };

    Func<CreateCourseRequest, CreateCourseResponse> func = 
          _courseAgent.CreateCourse;

    func.BeginInvoke(request, CreateCourseComplete, func);

}

The callback:

private void CreateCourseComplete(IAsyncResult ar)
{
    var caller = (Func<CreateCourseRequest, CreateCourseResponse>) ar.AsyncState;
    var result = caller.EndInvoke(ar);

    if (result.Status == ResponseBase.ResponseStatus.Successful)
    {
        _successful++;
    }
}

Any thoughts?

elucid8
  • 1,412
  • 4
  • 19
  • 40
  • 1
    congratulations, you asked a question about *async code* without showing any code which runs async. – I4V Aug 27 '13 at 22:22
  • @I4V Sorry about that. I've added the calls above. Again, this is a test application, so I'm not doing much with the results. – elucid8 Aug 27 '13 at 22:33

1 Answers1

0

My guess would be that you're catching an IOException, after you've started to write the file, and starting to write your document all over again.

Try trapping that exception and logging it.

And it's generally not a good sign when code traps an exception and ignores it.

Will Krause
  • 116
  • 5
  • I'm catching the IOException intentionally because I'm expecting to run into it. I want to attempt to access this file a certain number of times before giving up and handling it differently. – elucid8 Aug 27 '13 at 22:35
  • @elucid8 From looking at your code, I still think that you are getting an "unexpected" exception. It looks like you are expecting an "can't write to file", but you're encountering something else that is being thrown by `XElement.Save` after it has started writing to your stream. Try logging the exceptions as they occur, and you might find the answer. – Will Krause Aug 28 '13 at 02:03
  • @elucid8 Also, presuming I'm wrong about the exceptions, can you include a stack trace from your "multiple roots" exception? – Will Krause Aug 28 '13 at 02:06