从数据库和文件系统中删除文件

时间:2013-06-20 12:46:09

标签: c# entity-framework file

我有一个表引用我们网络上共享位置的文件(将文件路径存储在数据库中)。

我有一个按钮,需要从数据库中删除记录,文件系统中的文件:

foreach (var report in reports)
{
      string filePath = report.ReportPath;

      if (File.Exists(filePath));
      {
         File.Delete(filePath);
      }                      

      context.ReportGenerations.DeleteObject(report);
      context.SaveChanges();
}

删除文件或删除数据库记录时可能会抛出异常,如果发生这种情况,我希望这两种操作都不会完成。

是否有一种简单的方法可以确保两项操作都成功执行?

5 个答案:

答案 0 :(得分:20)

你必须做两件事

  • 将整个过程包装在数据库事务中。

  • 从文件系统中删除之前>

    中的文件

如果进程无法从数据库中删除,则由于您尚未访问文件系统删除逻辑,因此不会删除物理文件。

如果进程无法从文件系统中删除,则会回滚事务并恢复数据库操作。

DbTransaction transaction = null;
foreach (var report in reports)
{
    try
    {
        transaction = context.Connection.BeginTransaction();

        context.ReportGenerations.DeleteObject(report);
        context.SaveChanges();

        string filePath = report.ReportPath;
        if (File.Exists(filePath));
        {
            File.Delete(filePath);
        }
        transaction.Commit();
    }
    catch
    {
        transaction.Rollback();
    }
}        

<小时/> 虽然我认为这是一种更安全的方法,但您可以实现并不会变得非常复杂,我同意没有同步方法可以保证100%的功效。为了确保没有孤儿项目,您必须实施后台清理过程。根据您的情况,您必须分析这种额外的复杂性是否合理。

答案 1 :(得分:3)

在事务中从数据库和文件系统中删除文件:

using (TransactionScope scope = new TransactionScope(TransactionScope.Required, 
 new TransactionOptions 
     { IsolationLevel = IsolationLEvel.ReadCommitted}))
{
   try 
   {
       // Delete file from database
       // Delete physical file 
       // commit
   }
   catch (Exception ex)
   {
       // no commit, so database deletion will be rolled back
   }       
}

如果由于某种原因导致物理驱动器上的文件删除失败,则数据库删除也将被回滚。

如果数据库中的删除失败,则不会以物理方式删除该文件。

只有在物理删除和数据库删除都成功的情况下才会执行提交。

因此可能发生任何异常;你最终处于一致的状态。

答案 2 :(得分:1)

foreach (var report in reports)
{
      string filePath = report.ReportPath;
      string copyPath = @"C:\temp\tempFile.txt"
      try
      {
           if (File.Exists(filePath));
           {
              File.Copy(filePath, copyPath);
              File.Delete(filePath);
           }                      

           context.ReportGenerations.DeleteObject(report);
           context.SaveChanges();               
      }
      catch(Exception ex)
      {
           File.Copy(copyPath, filePath);
      }
      File.Delete(copyPath);
}

除了使用.txt,您还可以使用FileInfo获取filePath扩展名,如果它们全部不同,或者拆分为“。”并取split [1]值并追加到copyPath的末尾。由您决定

答案 3 :(得分:0)

.NET Transactional File Manager看起来对你要做的事情有用。这些示例似乎表明您可以将数据库操作和文件操作绑定到一个事务中。我从未使用它,所以我不能肯定地说。

编辑: 我查看了源代码,这个库没什么特别的。对于删除事务,它只是执行一个副本,然后删除,就像其他人在这里建议的那样。

答案 4 :(得分:-1)

解决方案是 1)将文件复制到其他临时位置,然后删除 2)成功删除后,从DB中删除记录 3)如果从DB抛出一些异常,则复制该文件并从临时位置删除该文件 4)如果evrything成功,则从临时位置清除文件。