hawkstrider
hawkstrider

Reputation: 4341

SQLite in 10 UWP App Assertion Error (p->iForeGuard==(int)FOREGUARD);

I have a Windows 10 Store app that is using SQLite and the SQLite.Net-PCL wrapper. SQLite is at version 3.9.2. All references are included (i.e SQLite for Universal App Platform, Visual C++ 2015 Runtime for Universal Windows Platform Apps, etc)

I am sporadically getting a C++ exception for Assertion Failed at assert( p->iForeGuard==(int)FOREGUARD );

There seems to be little information on this error. I understand that it is an assertion error (obviously :)) that is coming from the SQLite dll. I found a similar bug on another github project (https://github.com/mbrit/sqlite-metrostyle/issues/2) but this has no resolution either. Below is how I am creating my SQLite connection

private SQLiteConnection Connection
        => new SQLiteConnection(new SQLite.Net.Platform.WinRT.SQLitePlatformWinRT(), App.DBPath,
            SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.FullMutex | SQLiteOpenFlags.SharedCache);

I have played around with the open flags to no avail. I have multiple threads that may call SQLite and from what I can gather from the docs using FullMutex and SharedCache should allow for this (Please correct me if I am wrong)

I have since created a wrapper class to ensure that the connection was closed immediately since I read in a discussion that this may be the cause of the error. Here is an example of one of my wrapper methods

public T FirstOrDefault<T>(Func<T, bool> predicate) where T : class
{
    using (var conn = Connection)
    {
        var result = conn.Table<T>().FirstOrDefault(predicate);
        //Explicitly close the connection rather then wait for the dispose to do it
        conn.Close();
        return result;
    }            
}

This initially appeared to resolve the issue, but is has reared it's ugly head again. I am at a loss at this point. I have also tried using the SQLite.Net.Asyn-PCL library and that was no different as I would expect.

Any help or insight on this would be greatly appreciated.

Upvotes: 1

Views: 514

Answers (1)

hawkstrider
hawkstrider

Reputation: 4341

So I managed to get this issue resolved. Apparently in contradiction to how it was described as what should be done, a single connection to the database needs to be used. I was able to fix it by using a single SQLiteConnectionWithLock and using the Connection.Lock() when accessing the database.

Here is what I ended up using

private SQLiteConnectionWithLock _connection;

private SQLiteConnectionWithLock Connection
    =>
        _connection ??
        (_connection = new SQLiteConnectionWithLock(new SQLite.Net.Platform.WinRT.SQLitePlatformWinRT(),
            new SQLiteConnectionString(App.DBPath, false,
                openFlags:
                    SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.FullMutex |
                    SQLiteOpenFlags.SharedCache)));

Then when accessing the db used the connection lock

public int Count<T>() where T : class
{
    using (Connection.Lock())
    {
        var result = Connection.Table<T>().Count();
        return result;
    }
}

Upvotes: 3

Related Questions