gpt4 book ai didi

c# - 多线程应用程序中的 SQLite 事务

转载 作者:行者123 更新时间:2023-11-30 22:01:38 26 4
gpt4 key购买 nike

我做了一些搜索,我知道为了让同一个应用程序中的不同线程更新一个 SQLite 数据库文件,线程必须共享相同的 SQLiteConnection 对象。我已在我的申请中采取措施来实现这一目标。

我的问题与交易有关。我需要每个线程在一个事务中执行其更新,并且我需要每个事务与其他事务完全隔离。也就是说,在线程 A 中回滚或提交事务应该不会影响线程 B 正在完成的工作。

我是否必须做任何特殊的事情才能实现这一点,或者在每个线程的操作开始时创建一个 SQLiteTransaction 并将其分配给 SQLiteCommand 的事务属性(property)够不够?

最佳答案

在尝试了这个之后,我发现我之前关于需要跨线程共享单个连接的结论是错误的。现在每个线程:

  1. 使用一个名为 ConnectionManager 的特殊单例类创建 SQLiteConnection 实例,打开它们,并配置在每个连接打开后必须设置的通用设置。
  2. 通过调用 ConnectionManager 类中的方法在访问数据库之前创建一个新连接。
  3. 以常规方式启动和管理任何交易。
  4. 以通常的方式关闭并处理 SQLiteConnection

ConnectionManager 类允许所有需要连接到数据库的代码获得它们的连接,所有数据库设置都以一致的方式设置。我的代码需要设置的大多数属性实际上都在连接字符串中,但是有一个不能在那里指定,所以我需要另一种机制。下面是 ConnectionManager 的样子:

public class ConnectionManager {

public int BusyTimeout { get; set; }

public static ConnectionManager Instance {
get {
if ( iInstance == null ) {
lock ( instanceLock ) {
if ( iInstance == null )
iInstance = new ConnectionManager();
}
}
return iInstance;
}
}
private static ConnectionManager iInstance = null;

private static object instanceLock;

private ConnectionManager() {
BusyTimeout = Convert.ToInt32( TimeSpan.FromMinutes( 2 ).TotalMilliseconds );
}

static ConnectionManager() {
instanceLock = new object();
}

public SQLiteConnection CreateConnection( string connectionString ) {
SQLiteConnection connection = new SQLiteConnection( connectionString );
connection.Open();

using ( SQLiteCommand command = connection.CreateCommand() ) {
command.CommandText = string.Format( "PRAGMA busy_timeout={0}", BusyTimeout );
command.ExecuteNonQuery();
}
return connection;
}
}

要使用 ConnectionManager 类,将实例变量或局部变量设置为单例实例的副本,如下所示:

_connectionManager = ConnectionManager.Instance;

要获取和使用数据库连接,在每个线程中使用如下代码:

using ( SQLiteConnection connetion = _connectionManager.CreateConnection( connectionString ) {
// Thread's database operation code here
}

事实证明,让它工作的真正诀窍是将 busy_timeout pragma 设置为比默认值更长的时间。 SQLite 在内部是完全线程安全的,并自行序列化请求,因此您的代码只需要告诉 SQLite 等待任何当前正在执行的操作完成。我们的代码已经结构化,因此无论出于何种原因,数据库引擎中的故障都会导致操作在等待几秒钟后重试,因此效果很好。

默认的 2 分钟等待时间足以完成 99.99% 的所有操作。真的,如果某件事需要超过 2 分钟才能完成,我们需要重新访问该区域并以任何方式使其更快。

关于c# - 多线程应用程序中的 SQLite 事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27551763/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com