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

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

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

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

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

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

你必须做两件事

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

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

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

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

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

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

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

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

所以无论发生什么exception; 你最终处于一致的状态。

 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 Transactional File Manager看起来可能对您尝试执行的操作很有用。 这些示例似乎表明您可以将数据库操作和文件操作绑定到一个事务中。 我从未使用它,所以我不能肯定地说。

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

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