我在Android和iOS中使用库 SQLite.Net-PCL ,刚刚遇到错误。也许我误解了一些东西,但SQLite文档声明:
序列化即可。在序列化模式下,SQLite可以被多个安全使用 线程没有限制。
但是,当我通过多个线程共享连接时,似乎出现了问题。
我写了一个测试应用程序。见下文。
同时"同时"插入,我得 SQLite.Net.SQLiteException:误用。
这是完整的例外:
SQLite.Net.SQLiteException:误用于 SQLite.Net.PreparedSqlLiteInsertCommand.ExecuteNonQuery (System.Object [] source)[0x0016b] in < 8f2bb39aeff94a30a8628064be9c7efe>:0 at SQLite.Net.SQLiteConnection.Insert(System.Object obj,System.String extra,System.Type objType)[0x000fc] in < 8f2bb39aeff94a30a8628064be9c7efe>:0 at SQLite.Net.SQLiteConnection.Insert(System.Object obj)[0x00012] in < 8f2bb39aeff94a30a8628064be9c7efe>:0 at test.TestTask +<> c__DisplayClass4_0.b__0(System.Object aName) [0x00052]在/Users/dev/Documents/Xamarin/TestRepo/test/TestTask.cs:49
如果您之后查看数据库,它甚至看起来有重复的记录。
所以我的问题是:序列化模式是不是设计为在多个线程中使用单个连接?或者它是SQLite lib中的错误?
TestTask.cs(由Android和iOS共享):
using System;
using System.Threading.Tasks;
using SQLite.Net;
using SQLite.Net.Attributes;
using SQLite.Net.Interop;
namespace test
{
[Table("test_class")]
public class TestClass
{
[PrimaryKey, AutoIncrement, Column("_id")]
public int Id { get; set; }
[Column("caption")]
public string Caption { get; set; }
}
public static class TestTask
{
static Task taskA;
static Task taskB;
public delegate void OnMessage(string msg);
public static void Init(ISQLitePlatform platform, string path, OnMessage onMsg)
{
var con = new SQLiteConnection(platform, path);
con.CreateTable<TestClass>();
taskA = GetTask("First", con, onMsg);
taskB = GetTask("Second", con, onMsg);
}
static Task GetTask(string name, SQLiteConnection connection, OnMessage onMsg)
{
return new Task((aName) =>
{
int i = 0;
onMsg("Start " + aName);
for (i = 0; i < 1000; i++)
{
var obj = new TestClass
{
Caption = i + ": " + DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss:fff")
};
try
{
connection.Insert(obj);
}
catch (Exception e)
{
onMsg(aName + " -> " + "Index: " + i + " Error: " + e.Message);
}
}
onMsg("End " + aName);
},name);
}
public static void Run()
{
taskA.Start();
taskB.Start();
}
}
}
用法(iOS示例):
void HandleOnMessage(string msg)
{
UIApplication.SharedApplication.InvokeOnMainThread(() => Console.WriteLine(msg));
}
void DoIt()
{
var platform = new SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS();
platform.SQLiteApi.Config(ConfigOption.Serialized);
var path = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
path = Path.Combine(path, "test.db");
TestTask.Init(platform, path, HandleOnMessage);
TestTask.Run();
}
其他信息:
答案 0 :(得分:2)
我自己解决了。
这是“SQLite.Net PCL”Nuget Package中的一个问题。
在Connection上使用“sqlite-net-pcl”代替Read | Write | FullMutex Flags。 FullMutex标志强制执行序列化模式。