13

ネットワーク上の共有の場所にあるファイルを参照するテーブルがあります (データベースにファイル パスを保存します)。

データベースからレコードを削除し、ファイル システムからファイルを削除する必要があるボタンがあります。

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

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

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

ファイルを削除するとき、またはデータベース レコードを削除するときに例外がスローされる可能性があり、これが発生した場合、どちらの操作も完了させたくありません。

両方の操作が正常に実行されるようにする簡単な方法はありますか?

4

5 に答える 5

21

あなたは2つのことをしなければなりません

  • プロセス全体をデータベース トランザクション内にラップします。

  • ファイル システムからファイルを削除する前に、データベースからファイルを削除する

プロセスがデータベースからの削除に失敗した場合、ファイル システムの削除ロジックに達していないため、物理ファイルは削除されません。

プロセスがファイル システムからの削除に失敗すると、トランザクションがロールバックされ、データベース操作が元に戻ります。

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% の有効性を保証する同期アプローチは存在しないことに同意します。孤立したアイテムが残らないようにするには、バックグラウンド クリーンアップ プロセスを実装する必要があります。そのような余分な複雑さが正当化されるかどうか、シナリオに応じて分析する必要があります。

于 2013-06-20T12:49:48.853 に答える
0

.NET Transactional File Managerは、あなたがしようとしていることに役立つようです。これらの例は、データベース操作とファイル操作を 1 つのトランザクションにまとめることができることを示しているようです。使ったことがないので、はっきりとは言えません。

編集: ソース コードを確認しましたが、このライブラリは特別なことは何もしていません。削除トランザクションの場合、他の人がここで提案したように、コピーしてから削除するだけです。

于 2013-06-20T17:14:39.143 に答える