以事务方式删除目录

时间:2015-05-08 01:08:40

标签: c# .net

这与this question类似,但还有一个要求:

由于删除文件可能因任何原因而失败。所以我希望操作是"交易"这意味着整个行动要么全部成功,要么失败,不要改变任何事情。

总的来说,这将是非常非常困难的,当物理硬盘突然断裂时,我看不到任何恢复的可能性。所以一个弱化的条款是:如果成功,我们就完成了。否则,如果失败,请将所有内容恢复到原始状态,如果可能

我能想到的某种错误是:

  1. 访问冲突。您根本不允许删除某些文件或文件夹。这是我想要处理最多的情况。

  2. 文件/文件夹被其他人使用,因此它被锁定了#34;。在Linux中,这不是问题,但在Windows中它是。这也是有待处理的。

  3. 如果是网络文件夹,则可能存在网络问题。恢复可能很难或不可能。我不希望这种错误得到妥善处理。

  4. 硬件故障。我不认为这里会发生任何恢复。

  5. 方案

    您有一个可以导出其内部数据的软件。结果是在一个文件夹中,并且子文件夹名称带有时间戳。

    现在,如果用户指定了一个非空的文件夹(可能是以前的输出文件夹),软件将在其上创建新的子文件夹,这是一个质量。因此,在执行导出之前,您需要确保文件夹为空。

    如果没有,您可以轻松检测文件夹空白并提醒用户。但是如果用户说'#34;继续做下去"你应该做点什么。现在,如果您删除了某些文件并在其他文件上失败了怎么办?

    在这种情况下继续前进只会造成更大的质量。同时,如果没有任何工作,用户不会期望损坏的文件夹。因此,最好是给它们一个完全正常工作的输出,或者根本不改变以前的输出。

2 个答案:

答案 0 :(得分:2)

根据评论,我会给你编写代码的过程的伪代码:

Clear contents of cache folder if any files exist (they shouldn't)
Copy contents of destination folder to cache folder
Try
    While files exist, iterate
        Delete file
    End While
Catch
    While files exist in cache, iterate
        If file does not exist in destination folder
            Move file from cache to destination
        else
            Delete file from cache
        end If
    End While
End Try

答案 1 :(得分:0)

按照评论中给出的指导原则,我提出了这个解决方案。

以下代码将尝试将所有内容移动到给定folder内的临时文件夹中。如果成功,则返回True。如果失败,catch块将尝试将所有内容移回并返回False。在任何一种情况下,finally块都将递归删除临时文件夹。

public static bool EmptyFolderTransactionaly(string folder)
{
    var directoryInfo = new DirectoryInfo(folder);
    var tmpDir = Directory.CreateDirectory(Path.Combine(folder, Path.GetFileName(Path.GetTempFileName())));
    try
    {
        foreach (var e in directoryInfo.EnumerateFiles())
        {
            e.MoveTo(Path.Combine(tmpDir.FullName, e.Name));
        }
        foreach (var e in directoryInfo.EnumerateDirectories().Where(e => e.Name!=tmpDir.Name))
        {
            e.MoveTo(Path.Combine(tmpDir.FullName, e.Name));
        }
        return true;
    }
    catch
    {
        foreach (var e in tmpDir.EnumerateDirectories())
        {
            e.MoveTo(Path.Combine(directoryInfo.FullName, e.Name));
        }
        foreach (var e in tmpDir.EnumerateFiles())
        {
            e.MoveTo(Path.Combine(directoryInfo.FullName, e.Name));
        }
        return false;
    }
    finally
    {
        tmpDir.Delete(true);
    }
}

如果您发现代码中存在任何风险,请告诉我。