Reputation: 4341
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
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