Search code examples
c#sqlitefile-iowindows-store-appssqlite-net

Cant delete a file in Windows Store Application - Access is denied. (HRESULT: 0x80070005 (E_ACCESSDENIED))


I'm writing a Windows Store Application. I have to recreate a database in some cases (tests, new user, etc) - Sqlite is being used. I need to copy existing database to backup, delete existing database and then create a new database file with schema.

The code:

    public async Task<bool> CreateDatabaseAsync()
    {

        if (await PathUtils.FileExistsAsync(DbConstants.DbFileWithPath))
        {
            var currentDbFolder = await StorageFolder.GetFolderFromPathAsync(DbConstants.DbPath);
            var currentdbFile = await StorageFile.GetFileFromPathAsync(DbConstants.DbFileWithPath);
            await currentdbFile.CopyAsync(currentDbFolder, DbConstants.DbBackup, NameCollisionOption.ReplaceExisting);

            //problem here with deletion
            await currentdbFile.DeleteAsync(DbConstants.FilelDeletionOption);
        }
        return await CreateSchema();
    }

    private async Task<bool> CreateSchema()
    {
        var db = new SQLiteAsyncConnection(DbConstants.DbFileWithPath);
        await db.CreateTablesAsync(typeof (Doc), typeof(DocAttachment));
        db = null;
        GC.Collect();
        return true;
    }
}

If I call method CreateDatabaseAsync() two times sequentially, db file will be created during the first call and UnauthorizedAccessException will be thrown during its deletion during the second call - see the comment. I have no idea what can hold this file open. See that I null the reference to SQliteAsyncConnetion and force a collection of all generations. Still, I cannot delete the file - {"Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))"}.

File is being created in ApplicationData.Current.LocalFolder.Path.

Currently I'm trying to recreate the db during the each integration test.


Solution

  • The problem is that SQLiteAsyncConnection implements a connection pool - the pooling has the side effect of keeping the db file open.

    The only solution I can see is to use the synchronous version of the API. There is no pooling, and it allows you to close the db connection, and therefore close the file:

    private bool CreateSchema()
    {
        using (var db = new SQLiteConnection(DbConstants.DbFileWithPath))
        {
            db.CreateTables(typeof (Doc), typeof(DocAttachment));
        }
        return true;
    }