Locking XML file in Web Application

拥有回忆 提交于 2019-12-11 03:06:28

问题


We have a website application which acts as a form designer.

The form data is stored in XML file. Each form has it's own xml file.

When i edit a form, i basically recreate the XML file.

public void Save(Guid form_Id, IEnumerable<FormData> formData)
{
    XDocument doc = new XDocument();
    XElement formsDataElement = new XElement("FormsData");
    doc.Add(formsDataElement);
    foreach (FormData data in formData)
    {
        formsDataElement.Add(new XElement("FormData",
                                 new XAttribute("Id", data.Id)
                                 new XAttribute("Name", data.Name)
                                 // other attributes
                             ));
    }

    doc.Save(formXMLFilePath);
}

This works good, but i want to make sure that two users won't update at the same time the XML file. I want to lock it somehow.

How can i individually lock the save process for each file?

I could lock the Save function like below, but this will lock all the users, even if they save a different XML file.

private static readonly object _lock = new object();
public void Save(Guid form_Id, IEnumerable<FormData> formData)
{
    lock(_lock)
    {
        XDocument doc = new XDocument();
        foreach (FormData data in formData)
        {
            // Code
        }

        doc.Save(formXMLFilePath);
    }
}

回答1:


Try something like this:

FileStream file = new FileStream(formXMLFilePath,FileMode.Create,FileAccress.Write,FileShare.None);

try {
    doc.Save(file);
} finally {
    file.Close();
}

This uses a FileStream and we supply a FileShare mode. In our case we are exclusively locking the file so that only we can write to it.

However, this simply means that subsequent writes will fail as there is a lock.

To get around this problem I tend to have a queue and a separate thread who's only job is to process the queue and write to the file system.

However another solution is to simply try and access the file, and if that fails wait a little bit then try again. This would let you do something akin to lock where it waits until it can access and then proceeds:

private static bool IsLocked(string fileName)
{
    if (!File.Exists(fileName)) return false;

    try {
        FileStream file = new FileStream(fileName,FileMode.Open,FileAccess.Write,FileShare.None);

        try {
            return false;
        } finally {
            file.Close();
        }
    } catch (IOException) {
        return true;
    }
}

public void Save(Guid form_Id, IEnumerable<FormData> formData)
{
    while (IsLocked(formXMLFilePath)) Thread.Sleep(100);

    FileStream file = new FileStream(formXMLFilePath,FileMode.Create,FileAccress.Write,FileShare.None);

    try {
        doc.Save(file);
    } finally {
        file.Close();
    }
}



回答2:


To prevent files being written simultaneously, the XDocument.Save method internally creates a FileStream with the following constructor:

new FileStream(
    outputFileName,
    FileMode.Create,
    FileAccess.Write,
    FileShare.Read,
    0x1000,
    UseAsync)

The option FileShare.Read prevents multiple writes occuring simultaneously. If you attempted to perform two writes simultaneously, you'd wind up with an IOException being thrown.

You might want to write some code to deal with this eventuality. This answer https://stackoverflow.com/a/50800/138578 should provide exactly how to handle a file being locked and re-trying until the file becomes available.

If your documents are small and many, you shouldn't run into this situation very often, if at all.




回答3:


You did not closed your xml file connection after opening your xml file. So I think you need to first closed your connection at the end of your function.

you can use this

filename.Close();

I hope this will help you



来源:https://stackoverflow.com/questions/14316700/locking-xml-file-in-web-application

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!