Подтвердить что ты не робот

Удаление файла из базы данных и файловой системы

У меня есть таблица, которая ссылается на файлы в общей папке в нашей сети (сохраняет путь к файлу в базе данных).

У меня есть кнопка, которая должна удалить запись из базы данных и файла из файловой системы:

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

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

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

При удалении файла или удалении записи базы данных может быть выбрано исключение, и если это произойдет, я бы не хотел, чтобы ни одна из операций не завершилась.

Есть ли простой способ гарантировать, что обе операции выполнены успешно?

4b9b3361

Ответ 1

Вам нужно сделать две вещи

  • Оберните весь процесс внутри транзакции базы данных.

  • Удалить файл из базы данных до, выполнив его из файловой системы

Если процесс не удаляется из базы данных, физический файл не будет удален, так как вы не достигли логики удаления файловой системы.

Если процесс не удаляется из файловой системы, вы откатываете транзакцию транзакции и операции с базой данных.

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% эффективности. Чтобы быть уверенным, что ни один сиротский элемент не останется, вам нужно будет выполнить процесс очистки фона. Вам придется проанализировать, оправдана ли такая дополнительная сложность или нет по вашему сценарию.

Ответ 2

Удалите файл из базы данных и файловой системы в транзакции:

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

Если по какой-либо причине удаление файла на физическом диске сбой по какой-либо причине, удаление базы данных также будет отменено.

Если удаление в базе данных не удалось, файл не будет удален физически.

Commit выполняется только в том случае, если удалено как физическое удаление, так и удаление базы данных.

Таким образом, любое исключение может возникнуть; вы попадаете в согласованное состояние.

Ответ 3

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 on. и взять значение split [1] и добавить к концу copyPath. До вас

Ответ 4

.NET Transactional File Manager выглядит так, как будто это может быть полезно для того, что вы пытаетесь сделать. В примерах показано, что вы можете связать операцию с базой данных и операцию файла вместе в одну транзакцию. Я никогда не использовал его, поэтому не могу сказать наверняка.

Изменить: Я посмотрел исходный код, и эта библиотека ничего особенного не делает. Для транзакции удаления она просто копирует, а затем удаляет, как это предложили другие.

Ответ 5

Решение будет 1) Скопируйте файл в другое временное место, а затем удалите.
2) При успешном удалении удалите запись из БД.
3) Если какое-то исключение выбрано из БД, скопируйте файл и удалите файл из временного местоположения.
4) Если evrything успешно, то очистите файл от временного местоположения.