gpt4 book ai didi

sqlite - System.Data.SQLite Close() 不释放数据库文件

转载 作者:IT王子 更新时间:2023-10-29 06:16:52 25 4
gpt4 key购买 nike

我在尝试删除文件之前关闭数据库时遇到问题。代码只是

 myconnection.Close();    
File.Delete(filename);

并且 Delete 抛出一个文件仍在使用中的异常。几分钟后,我在调试器中重新尝试了 Delete(),所以这不是时间问题。

我有事务代码,但它在 Close() 调用之前根本不运行。所以我相当确定这不是公开交易。 open和close之间的sql命令只是select。

ProcMon 显示我的程序和我的防病毒软件查看数据库文件。它没有显示我的程序在 close() 之后释放 db 文件。

Visual Studio 2010、C#、System.Data.SQLite 版本 1.0.77.0、Win7

我看到了一个两年前的错误,就像这样,但变更日志说它已修复。

还有什么我可以检查的吗?有没有办法获取任何打开的命令或事务的列表?


新的工作代码:

 db.Close();
GC.Collect(); // yes, really release the db

bool worked = false;
int tries = 1;
while ((tries < 4) && (!worked))
{
try
{
Thread.Sleep(tries * 100);
File.Delete(filename);
worked = true;
}
catch (IOException e) // delete only throws this on locking
{
tries++;
}
}
if (!worked)
throw new IOException("Unable to close file" + filename);

最佳答案

不久前在为 C# 编写 DB 抽象层时遇到了同样的问题,但我从来没有真正抽出时间找出问题所在。当您尝试使用我的库删除 SQLite 数据库时,我刚刚抛出异常。

无论如何,今天下午我再次仔细查看了所有内容,并想我会一劳永逸地找出它这样做的原因,所以这是我到目前为止所发现的。

当您调用 SQLiteConnection.Close() 时会发生什么(连同许多检查和其他事情)指向 SQLite 数据库实例的 SQLiteConnectionHandle 是处置。这是通过调用 SQLiteConnectionHandle.Dispose() 完成的,但是在 CLR 的垃圾收集器执行一些垃圾收集之前,这实际上并没有释放指针。由于 SQLiteConnectionHandle 覆盖了 CriticalHandle.ReleaseHandle() 函数来调用 sqlite3_close_interop()(通过另一个函数),这不会关闭数据库。

在我看来,这是一种非常糟糕的做事方式,因为程序员实际上并不确定数据库何时关闭,但这就是它已经完成的方式,所以我想我们现在必须接受它,或对 System.Data.SQLite 进行一些更改。欢迎任何志愿者这样做,不幸的是我明年之前没有时间这样做。

长话短说解决方案是在调用 SQLiteConnection.Close() 之后和调用 File.Delete() 之前强制执行 GC。

示例代码如下:

string filename = "testFile.db";
SQLiteConnection connection = new SQLiteConnection("Data Source=" + filename + ";Version=3;");
connection.Close();
GC.Collect();
GC.WaitForPendingFinalizers();
File.Delete(filename);

祝你好运,希望对你有帮助

关于sqlite - System.Data.SQLite Close() 不释放数据库文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8511901/

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