C# 在Web应用程序中锁定XML文件

C# 在Web应用程序中锁定XML文件,c#,asp.net,locking,linq-to-xml,C#,Asp.net,Locking,Linq To Xml,我们有一个网站应用程序,作为一个表单设计师 表单数据存储在XML文件中。每个表单都有自己的xml文件 当我编辑表单时,基本上是重新创建XML文件 public void Save(Guid form_Id, IEnumerable<FormData> formData) { XDocument doc = new XDocument(); XElement formsDataElement = new XElement("FormsData"); doc.Ad

我们有一个网站应用程序,作为一个表单设计师

表单数据存储在XML文件中。每个表单都有自己的xml文件

当我编辑表单时,基本上是重新创建XML文件

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);
}
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);
    }
}
public void Save(Guid form\u Id,IEnumerable formData)
{
XDocument doc=新XDocument();
XElement formsDataElement=新XElement(“FormsData”);
单据新增(formsDataElement);
foreach(FormData中的FormData数据)
{
添加(新的XElement(“FormData”),
新XAttribute(“Id”,data.Id)
新XAttribute(“Name”,data.Name)
//其他属性
));
}
单据保存(formXMLFilePath);
}
这很好,但我想确保两个用户不会同时更新XML文件。我想把它锁起来

如何单独锁定每个文件的保存过程

我可以像下面那样锁定Save函数,但这将锁定所有用户,即使他们保存不同的XML文件

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);
}
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);
    }
}
私有静态只读对象_lock=new object();
public void Save(Guid form\u Id,IEnumerable formData)
{
锁
{
XDocument doc=新XDocument();
foreach(FormData中的FormData数据)
{
//代码
}
单据保存(formXMLFilePath);
}
}

尝试以下方法:

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

try {
    doc.Save(file);
} finally {
    file.Close();
}
这使用了
FileStream
,我们提供了
FileShare
模式。在我们的例子中,我们以独占方式锁定该文件,以便只有我们可以对其进行写入

然而,这仅仅意味着后续写入将失败,因为存在锁

为了解决这个问题,我倾向于使用一个队列和一个单独的线程,该线程的唯一任务是处理队列并写入文件系统

然而,另一种解决方案是尝试访问该文件,如果失败,请稍等片刻,然后重试。这将允许您执行类似于锁定的操作,在该操作中,它将等待,直到可以访问,然后继续:

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();
    }
}
private static bool已锁定(字符串文件名)
{
如果(!File.Exists(fileName))返回false;
试一试{
FileStream file=newfilestream(文件名,FileMode.Open,FileAccess.Write,FileShare.None);
试一试{
返回false;
}最后{
file.Close();
}
}捕获(IOException){
返回true;
}
}
public void Save(Guid form\u Id,IEnumerable formData)
{
while(IsLocked(formXMLFilePath))Thread.Sleep(100);
FileStream file=newfilestream(formXMLFilePath,FileMode.Create,fileaclass.Write,FileShare.None);
试一试{
单据保存(文件);
}最后{
file.Close();
}
}

尝试以下方法:

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

try {
    doc.Save(file);
} finally {
    file.Close();
}
这使用了
FileStream
,我们提供了
FileShare
模式。在我们的例子中,我们以独占方式锁定该文件,以便只有我们可以对其进行写入

然而,这仅仅意味着后续写入将失败,因为存在锁

为了解决这个问题,我倾向于使用一个队列和一个单独的线程,该线程的唯一任务是处理队列并写入文件系统

然而,另一种解决方案是尝试访问该文件,如果失败,请稍等片刻,然后重试。这将允许您执行类似于锁定的操作,在该操作中,它将等待,直到可以访问,然后继续:

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();
    }
}
private static bool已锁定(字符串文件名)
{
如果(!File.Exists(fileName))返回false;
试一试{
FileStream file=newfilestream(文件名,FileMode.Open,FileAccess.Write,FileShare.None);
试一试{
返回false;
}最后{
file.Close();
}
}捕获(IOException){
返回true;
}
}
public void Save(Guid form\u Id,IEnumerable formData)
{
while(IsLocked(formXMLFilePath))Thread.Sleep(100);
FileStream file=newfilestream(formXMLFilePath,FileMode.Create,fileaclass.Write,FileShare.None);
试一试{
单据保存(文件);
}最后{
file.Close();
}
}

打开xml文件后,您没有关闭xml文件连接。因此,我认为您需要在函数结束时首先关闭连接

你可以用这个

filename.Close();

我希望这将对您有所帮助

您在打开xml文件后没有关闭xml文件连接。因此,我认为您需要在函数结束时首先关闭连接

你可以用这个

filename.Close();

我希望这将帮助您

防止同时写入文件,
XDocument.Save
方法在内部使用以下构造函数创建一个
FileStream

new FileStream(
    outputFileName,
    FileMode.Create,
    FileAccess.Write,
    FileShare.Read,
    0x1000,
    UseAsync)
选项
FileShare.Read
可防止同时发生多个写操作。如果您试图同时执行两次写入,则会引发
IOException

您可能需要编写一些代码来处理这种情况。这个答案应该准确地提供如何处理被锁定的文件,并在文件可用之前重新尝试


如果您的文档又小又多,您不应该经常遇到这种情况。

为了防止同时写入文件,
XDocument.Save
方法在内部使用以下构造函数创建一个
FileStream

new FileStream(
    outputFileName,
    FileMode.Create,
    FileAccess.Write,
    FileShare.Read,
    0x1000,
    UseAsync)
选项
FileShare.Read
可防止同时发生多个写操作。如果您试图同时执行两次写入,则会引发
IOException

您可能需要编写一些代码来处理这种情况。这个答案应该准确地提供如何处理被锁定的文件,并在文件可用之前重新尝试


如果您的文档又小又多,您不应该经常遇到这种情况(如果有的话)。

您说的是“文件”。您是否将XML文档存储到Windows文件系统?是的,我将XML文件保存在硬盘上