0

I have a problem with encapsulated try/catch blocks in combination with DbContexts from EF.

my code is seen in the following:

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

In SqlCeToSqLite the following is used:

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

This is basically copying the tables from testcontext to a new context (emptydbcontext). When an exception is thrown, I want to restore from a previously made backup, which is done in the RepairComplete() function. This involves first deleting all items in the datapath, and then moving the ones from the backup there.

However, when I want to delete the database created by the emptydbcontext, it throws an IOException "The process cannot access the file '9622241.s3db' because it is being used by another process.".

This tells me the context is still open, though it should have been disposed when leaving the using() block with an exception? Collecting garbage for clearing any to be disposed objects didn't help. RepairComplete doesn't create any contexts, it just deletes the files (there it crashes) and then moves the backup'ed files.

Why doesn't it work like that, shouldn't the context be disposed when leaving the using block + going through GC? What can I do to fix this issue?

DevilSuichiro
  • 1,049
  • 8
  • 21

1 Answers1

0

Alright, there are a few things I have tried. First I read to rebuild the used Sqlite dll's, because it seems to be a EF+Sqlite related issue, as suggested in this post.

However, with the updated sources it still didn't work. Right now I suspect it had to do with calling GC AFTER the context has been disposed and error handling ended, I think EF stores its commands even after the disposal of the context for reference.

Now I went over to Error Handling right in the function where the error occurs (in the using block) like this:

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

With the call to suppressFinalize to not Dispose the already disposed context when the using block ends (though it was never an issue for me), it now works. Of course it's only with a call to GC.Collect(), which in itself is not quite reliable, so I'd like to have a better option, but at least it works for some right now.

Community
  • 1
  • 1
DevilSuichiro
  • 1,049
  • 8
  • 21