We are using the System.Data.SQLite Wrapper in Version 1.0.80. Using this to establish multiple connections to a single SQLite database will show a weird behaviour.
We ensure having just one writable connection and multiple read-only connections.
When the first established connection is a read-only connection (using the connection string parameter Read Only=true) the second connection (which is writable due to missing read-only parameter) does not persist changes. There are no exceptions thrown either. If we turn it around, so we first establish write access and the read-only connection later, persisting changes is not a problem.
The problem is, in our code we cannot ensure which connection to a SQLite database file is used first and using multiple write connections lead to deadlock situations.
Does somebody know about this bug? Is there a workaround available?
Some source code:
private static void Test() {
string fileFullPath = "\\Flash\\test.db";
IDbConnection readCon = new SQLiteConnection(@"Data Source=" + fileFullPath + ";Read Only=true");
readCon.Open();
using (IDbCommand cmd = readCon.CreateCommand())
{
cmd.CommandText = "PRAGMA synchronous=OFF";
cmd.ExecuteNonQuery();
}
using (IDbCommand cmd = readCon.CreateCommand())
{
cmd.CommandText = "PRAGMA journal_mode=OFF";
cmd.ExecuteNonQuery();
}
using (IDbCommand cmd = readCon.CreateCommand())
{
cmd.CommandText = "SELECT * FROM tbltest WHERE foo = 'bar'";
Console.WriteLine(cmd.ExecuteReader().Read());// FALSE as expected
}
// readcon still open
// open a writable connection
IDbConnection con = new SQLiteConnection(@"Data Source=" + fileFullPath);
con.Open();
using (IDbCommand cmd = con.CreateCommand())
{
cmd.CommandText = "PRAGMA synchronous=OFF";
cmd.ExecuteNonQuery();
}
using (IDbCommand cmd = con.CreateCommand())
{
cmd.CommandText = "PRAGMA journal_mode=OFF";
cmd.ExecuteNonQuery();
}
IDbTransaction transaction = con.BeginTransaction();
using (IDbCommand cmd = con.CreateCommand())
{
cmd.CommandText = "INSERT INTO tbltest(foo) values('bar')";
cmd.ExecuteNonQuery();
}
transaction.Commit();// persisting occurs here
using (IDbCommand cmd = readCon.CreateCommand())
{
cmd.CommandText = "SELECT * FROM tbltest WHERE foo = 'bar'";
Console.WriteLine(cmd.ExecuteReader().Read());// TRUE as expected
}
con.Close();
readCon.Close();
// verify writing
readCon = new SQLiteConnection(@"Data Source=" + fileFullPath + ";Read Only=true");
readCon.Open();
using (IDbCommand cmd = readCon.CreateCommand())
{
cmd.CommandText = "SELECT * FROM tbltest WHERE foo = 'bar'";
Console.WriteLine(cmd.ExecuteReader().Read()); // TRUE expected but we get FALSE
}
readCon.Close();
}
Output:
FALSE
TRUE
FALSE
Thanks for your help, schibbl