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

本文关键字:删除 文件 文件系统 数据库 | 更新日期: 2023-09-27 18:19:16

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

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

foreach (var report in reports)
{
      string filePath = report.ReportPath;
      if (File.Exists(filePath));
      {
         File.Delete(filePath);
      }                      
      context.ReportGenerations.DeleteObject(report);
      context.SaveChanges();
}

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

有没有一种简单的方法可以确保两个操作都成功进行?

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

你必须做两件事

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

  • 文件系统中删除文件之前从数据库中删除文件

如果该过程从数据库删除失败,则不会删除物理文件,因为尚未达到文件系统删除逻辑。

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

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% 的有效性。若要确保没有孤立项,必须实现后台清理过程。您必须根据您的方案分析这种额外复杂性是否合理。

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

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
   }       
}

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

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

仅当物理删除和数据库删除都成功时,才会执行提交。

因此,无论发生什么异常;您最终都会处于一致的状态。

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 的末尾。轮到你了

.

NET 事务文件管理器看起来可能对您尝试执行的操作有用。这些示例似乎表明,您可以将数据库操作和文件操作绑定到单个事务中。我从来没有用过它,所以我不能肯定地说。

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

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