2015-09-10 2 views
0

У меня проблема с инкапсулированными блоками try/catch в сочетании с DbContexts из EF.Исключение при использовании блоков для DbContext

мой код рассматривается в следующем:

var hasToBeRepaired = false; 
Exception ex = null; 
try 
{ 
    SqlCeToSqLite(testContext); 
} 
catch(Exception exc) 
{ 
    hasToBeRepaired = true; 
    ex = exc; 
} 
if (hasToBeRepaired) 
{ 
    testContext.Dispose(); 
    GC.Collect(); 
    RepairComplete(_bl.BlShip.Imo, backupLastCe.BackUpPath); 
} 

В SqlCeToSqLite используется следующее:

using(var emptydbcontext = new WriteObjectsContext(builder.ToString(), Providers.SqLite)) 
     { 
      .... 
     } 

В основном это копирование таблицы из TestContext в новый контекст (emptydbcontext). Когда возникает исключение, я хочу восстановить из ранее сделанной резервной копии, которая выполняется в функции RepairComplete(). Это включает в себя сначала удаление всех элементов в datapath, а затем перемещение их из резервной копии.

Однако, когда я хочу удалить базу данных, созданную emptydbcontext, она выдает исключение IOException «Процесс не может получить доступ к файлу« 9622241.s3db », потому что он используется другим процессом.».

Это говорит мне, что контекст по-прежнему открыт, хотя он должен был быть удален при выходе из блока using() с исключением? Сбор мусора для очистки любых объектов, находящихся в распоряжении, не помог. RepairComplete не создает никаких контекстов, он просто удаляет файлы (там он сбой), а затем перемещает файлы резервной копии.

Почему он не работает так, разве контекст не должен удаляться при выходе из блока использования + через GC? Что я могу сделать, чтобы исправить эту проблему?

ответ

0

Хорошо, есть несколько вещей, которые я пробовал. Сначала я прочитал, чтобы перестроить используемую dll Sqlite, потому что это похоже на проблему с EF + Sqlite, как предложено in this post.

Однако, с обновленными источниками оно все еще не работает. Сейчас я подозреваю, что это связано с вызовом GC ПОСЛЕ того, как контекст был удален, и обработка ошибок закончилась, я думаю, что EF сохраняет свои команды даже после удаления контекста для справки.

Теперь я подошел к Error Handling прямо в функции, где произошла ошибка (в использовании блока), как это:

using(var emptydbcontext = new WriteObjectsContext(builder.ToString(), Providers.SqLite)) 
    { 
     try 
     { 
      .... 
     } 
     catch(Exception) 
     { 
      GC.SuppressFinalize(emptydbcontext); 
      emptydbcontext.Dispose(); 
      GC.Collect(); 
      throw; 
     } 
    } 

С вызовом SuppressFinalize не Выбросьте уже размещенный контекст при использовании конец блока (хотя это никогда не было проблемой для меня), теперь он работает. Конечно, только с вызовом GC.Collect(), который сам по себе не совсем надежный, поэтому я бы хотел иметь лучший вариант, но по крайней мере он работает для некоторых прямо сейчас.

Смежные вопросы