SQLite:与一个文件的多个连接 - 唯一可写的文件不会被保留

时间:2013-06-07 13:22:21

标签: sqlite transactions database-connection system.data.sqlite data-loss

我们在版本1.0.80中使用System.Data.SQLite Wrapper。使用它来建立与单个SQLite数据库的多个连接将显示一种奇怪的行为。

我们确保只有一个可写连接和多个只读连接。

当第一个建立的连接是只读连接时(使用连接字符串参数Read Only = true),第二个连接(由于缺少只读参数而可写)不会保持更改。也没有抛出异常。 如果我们转过来,所以我们先建立写访问权限和以后的只读连接,持久化更改不是问题。

问题是,在我们的代码中,我们无法确保首先使用与SQLite数据库文件的哪个连接,并且使用多个写连接会导致死锁情况。

有人知道这个错误吗?有可用的解决方法吗?

一些源代码:

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();
}

输出:

FALSE
TRUE
FALSE

感谢您的帮助, schibbl

0 个答案:

没有答案