SQLCipher RT Additional information: file is encrypted or is not a database

Scenario:
1)We have an app already on Widows Store (SQLCipher RT) "OurApp 1.0.0.1"
All warkd ok.
2)When user update Widows Store “OurApp 1.0.0.1” to Widows Store "OurApp 1.0.0.2"
We get: Additional information: file is encrypted or is not a database on trying to connect to DB
3)When DB file on Widows Store “OurApp 1.0.0.2” removed and created again by initialize all works fine
but we don’t wan’t our users lost theirs data!!!

Problem is App update from 1.0.0.1 app instance to 1.0.0.2 on Windows Store
On Windows Phone 8 same scenario works

Hello @filipoff

Where are you storing your database file? Also, are you applying any schema changes to your application in the new 1.0.0.2 version?

public static readonly string DbFileName = Path.Combine(ApplicationData.Current.LocalFolder.Path, "some_database.db");
    public const string DbPassword = "som_pass";

    public async Task InitializeDatabase()
    {
        var connection = new SQLiteAsyncConnection(DbFileName, DbPassword); //Connected

        // Temp tables stored in memory
        await connection.ExecuteAsync("PRAGMA temp_store = memory;");//this is executed and works


        Database.Current.Connection = connection;

        await Database.Current.Initialize(); //ERRROR

   }

    public async Task<bool> Initialize()
    {
        bool isFirstInit = await IsDatabaseEmpty(); ///ERROR (file is encryption)
        
        if (isFirstInit)
        {
            await CreateTables();
        }

        await PerformDatabaseSchemaUpdate();///Altering columns

        return isFirstInit;
    }

    private async Task<bool> IsDatabaseEmpty()
    {
        string nonSystemTablesCount = string.Format(
            "SELECT count(*) as IntValue FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'");

        List<IntWrapper> result = await Connection.QueryAsync<IntWrapper>(nonSystemTablesCount);  //ERROR

// query (any select) is error
//IntWrapper works in normal scenario

        return result.First().IntValue == 0;
    }

Hello @filipoff

It would be helpful to see what the Database class looks like, in particular the Initialize method.

namespace myApp.name
{
public class Database
{
private ISQLiteAsyncConnection _connection;
public ISQLiteAsyncConnection Connection
{
get
{
if (_connection == null)
throw new ArgumentNullException(“Connection has not been opened”);

            return _connection;
        }
        set
        {
            _connection = value;
        }
    }

    private static Database _current;
    public static Database Current
    {
        get
        {
            if (_current == null)
                _current = new Database();

            return _current;
        }
    }

    public async Task<bool> Initialize()
    {
        bool isFirstInit = await IsDatabaseEmpty();

        if (isFirstInit)
        {
            await CreateTables();
        }

        await PerformDatabaseSchemaUpdate();

        return isFirstInit;
    }

    private async Task PerformDatabaseSchemaUpdate()
    {
        // Alter table queries
    }

    private async Task CreateTables()
    {
        await Connection.CreateTableAsync<TableName1>();
        await Connection.CreateTableAsync<TableName2>();
        ...
    }

    private async Task<bool> IsDatabaseEmpty()
    {
        string nonSystemTablesCount = string.Format(
            "SELECT count(*) as IntValue FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'");

        List<IntWrapper> result = await Connection.QueryAsync<IntWrapper>(nonSystemTablesCount);

        return result.First().IntValue == 0;
    }
}

public class IntWrapper
{
    public int IntValue { get; set; }
}

}

Hello @filipoff

The behavior within the IsDatabaseEmpty() function is generally implemented via issuing a PRAGMA user_version; command. This will provide the current schema version of the application, which will default to 0 when not set, but can then be incremented via PRAGMA user_version = N; where N is a numeric value. Are you able to reproduce the behavior locally when you increment the version of the application itself?

await connection.ExecuteAsync(“PRAGMA user_version = 0”); //error
//this code throws such exception
An exception of type ‘SQLite.SQLiteException’ occurred in MyApp.Store.exe but was not handled in user code
Additional information: NonDBFile

I just ran the following example successfully, can you try this:

public async void SampleUserVersion()
{
  SQLiteAsyncConnection con;
  con = new SQLiteAsyncConnection(databasePath, "Password1!");
  await con.ExecuteAsync("PRAGMA user_version = 5;", new Object[] { });
  var currentVersion = await con.ExecuteScalarAsync<int>("PRAGMA user_version;", new Object[] { });
  System.Diagnostics.Debug.WriteLine("Current version:{0}", currentVersion);
}

Also, are you able to reproduce this database file being replaced/recreated locally?

  1. recreation = works fine

  2. replacement between instances of app 1.0.0.2 file from 1 = works fine

  3. bad scenario is update off app from 1.0.0.1 to 1.0.0.2
    a) I don’t know on what variables is SQLCipher decides that some.db file version is not good for my
    b) I know i make kind off successful connection that is some await con.ExecuteAsync("PRAGMA works other not
    other queries also don’t work i get error like in title.
    c) I assume that some VS Windows Store App Packager in Release (not debug) for x64 produce this bug (changing db file version?)

Additionally changes between my App version 1.0.0.1 and 1.0.0.2
are added columns on TableName1
await Connection.CreateTableAsync < TableName1>();
but it should have any impact on possibly to connect with password to encrypted DB
how it wrote it works fine on WP8 and it don’t on RT (Windows Store App)

What is more ,It is NOT such scenarios:

  1. For sure password is same
  2. http://stackoverflow.com/questions/18589280/sqlite3-databaseerror-file-is-encrypted-or-is-not-a-database
    I have same SQLlight.dll, and SQLClipher same version

Ok,
It was my configuration in V1 and in V2 related with using SQLClipher (data issues).
SQLClipher WORKS FINE!!!
There is no problem, sorry.

Hello @filipoff

We are glad to hear you resolved the issue. Could you expand on what you did to resolve it, in case someone else were to report the same thing? Thanks!