通过System.Data.SQLite和c#对单个SQLite数据库文件进行多重访问
本文关键字:SQLite 文件 数据库 访问 单个 Data System 通过 | 更新日期: 2023-09-27 18:03:36
我可以从SQLite FAQ中读取它支持多进程读取(SELECT)和只有一个进程写入(INSERT, UPDATE, DELETE)数据库在任何时刻:
SQLite使用读写锁来控制对数据库的访问。当任何进程想要写入时,它必须锁定整个数据库文件在其更新期间。但这通常只需要几个毫秒。其他进程只是等待写程序完成继续他们的业务
我使用System.Data。SQLite适配器通过c#.
是否有人可以解释一下,究竟这个过程是如何进行的?
这个过程是否自动工作,如果有另一个写SQLiteCommand已经在同一数据库上执行,那么写SQLiteCommand将简单地等待?
或者可能会抛出一个异常?什么样的?
对不起,但是我没有找到关于这个机制的信息:)
谢谢。
更新:
我发现一个帖子说异常将被引发带有一个特定的错误码
这个说法正确吗?
我已经亲自调查过了:
我创建了一个示例SQLite数据库c:'123.db
,其中一个表Categories
包含两个字段:ID
(惟一标识符)和Name
(nvarchar)。
然后我写了一些多线程代码来模拟对数据库的多次写访问(如果使用此代码,请不要忘记为您的项目添加System.Data.SQLite
引用):
using System;
using System.Data.SQLite;
using System.Threading.Tasks;
namespace SQLiteTest
{
class Program
{
static void Main(string[] args)
{
var tasks = new Task[100];
for (int i = 0; i < 100; i++)
{
tasks[i] = new Task(new Program().WriteToDB);
tasks[i].Start();
}
foreach (var task in tasks)
task.Wait();
}
public void WriteToDB()
{
try
{
using (SQLiteConnection myconnection = new SQLiteConnection(@"Data Source=c:'123.db"))
{
myconnection.Open();
using (SQLiteTransaction mytransaction = myconnection.BeginTransaction())
{
using (SQLiteCommand mycommand = new SQLiteCommand(myconnection))
{
Guid id = Guid.NewGuid();
mycommand.CommandText = "INSERT INTO Categories(ID, Name) VALUES ('" + id.ToString() + "', '111')";
mycommand.ExecuteNonQuery();
mycommand.CommandText = "UPDATE Categories SET Name='222' WHERE ID='" + id.ToString() + "'";
mycommand.ExecuteNonQuery();
mycommand.CommandText = "DELETE FROM Categories WHERE ID='" + id.ToString() + "'";
mycommand.ExecuteNonQuery();
}
mytransaction.Commit();
}
}
}
catch (SQLiteException ex)
{
if (ex.ReturnCode == SQLiteErrorCode.Busy)
Console.WriteLine("Database is locked by another process!");
}
}
}
}
在我的Core2Duo E7500的结果是,异常永远不会引发!
看起来SQLite已经优化到足以满足我的需求(锁/解锁真的很快,通常只需要几毫秒,正如SQLite FAQ告诉我们的那样)-太棒了!
请注意,不需要为SQLiteException
检索整数ErrorCode -您可以使用特殊的enum ReturnCode
字段来代替。所有代码都在这里描述。