我正试图从我的C#应用程序中删除一个SQLite数据库文件。同一应用程序通过每次创建和处理新连接来执行多个可读写(RW)查询。
当尝试删除数据库时(在我可以保证程序没有查询数据库的时刻,因此没有活动连接),我遇到了以下错误:
IOException: The process cannot gain access to <filename> because is being used by another process.
我调查了几个小时:我的代码,Stack Overflow 的问题,使用 procmon 和 resmon 确保我的进程是唯一持有文件活动句柄的进程。
在所有这些之后,我确定每当创建一个数据库连接时,DB 文件没有被正确关闭。下面是解释:
我有以下函数来执行查询并将结果加载到 DataTable
中:
public DataTable PerformQuery(string query) {
try {
DataTable table = new DataTable();
using(SQLiteConnection connection = new SQLiteConnection(connString)) {
SQLiteCommand cmd = connection.CreateCommand();
cmd.CommandText = query;
connection.Open();
if (!query.StartsWith("SELECT")) {
cmd.ExecuteNonQuery();
} else {
SQLiteDataReader reader = cmd.ExecuteReader();
FillTable(reader, table);
}
// Despite using the using scope, close and dispose the connection manually
connection.Close();
connection.Dispose();
}
// Kill all pools and call GC
SQLiteConnection.ClearAllPools();
GC.Collect();
GC.WaitForPendingFinalizers();
return table;
} catch (Exception ex) {
// Handle error... (not relevant)
return null;
}
}
嗯,使用SysInternals的handle.exe
在一个无限循环中(每秒运行一次),并使用Visual Studio的调试器逐步调试程序,我发现尽管:
- 调用
Close
- 调用
Dispose
- 退出
using
范围 - 杀死所有池
- 执行GC并等待其完成
我的DB文件的文件句柄没有被关闭。
我真的需要从代码内部删除我的DB文件,但由于文件句柄从未关闭,我无法这样做。
我该如何解决这个问题?
编辑1:
- 使用.NET Winforms应用程序和
System.Data.SQLite
- 已经尝试将
Pooling=false
添加到连接字符串中。
System.Data.SQLite
。 - PauMAVA