System.Data.SQLite Close() 不释放数据库文件 [英] System.Data.SQLite Close() not releasing database file

查看:36
本文介绍了System.Data.SQLite Close() 不释放数据库文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 myconnection.Close();File.Delete(文件名);

并且删除会引发文件仍在使用中的异常.几分钟后,我在调试器中重新尝试了 Delete(),所以这不是时间问题.

我有事务代码,但它在 Close() 调用之前根本没有运行.所以我很确定这不是一个公开的交易.open 和 close 之间的 sql 命令只是选择.

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

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

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

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

<小时>

新的工作代码:

 db.Close();GC.Collect();//是的,真的释放数据库布尔工作=假;int 尝试 = 1;while ((trys <4) && (!worked)){试试{Thread.Sleep(尝试 * 100);File.Delete(文件名);工作=真;}catch (IOException e)//删除只在锁定时抛出这个{尝试++;}}如果(!工作)throw new IOException("无法关闭文件" + 文件名);

解决方案

不久前在为 C# 编写数据库抽象层时遇到了同样的问题,但我实际上一直没有时间找出问题所在.当您尝试使用我的库删除 SQLite 数据库时,我刚刚抛出异常.

无论如何,今天下午我再次浏览了所有内容,并认为我会尝试找出为什么它会一劳永逸地这样做,所以这是我迄今为止发现的内容.

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

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

TL;DR解决方案是在调用 SQLiteConnection.Close() 之后和调用 File.Delete() 之前强制执行 GC.

这是示例代码:

string filename = "testFile.db";SQLiteConnection connection = new SQLiteConnection("Data Source=" + filename + ";Version=3;");连接.关闭();GC.Collect();GC.WaitForPendingFinalizers();File.Delete(文件名);

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

I'm having a problem closing my database before an attempt to delete the file. The code is just

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

And the Delete throws an exception that the file is still in use. I've re-tried the Delete() in the debugger after a few minutes, so it's not a timing issue.

I have transaction code but it doesn't run at all before the Close() call. So I'm fairly sure it's not an open transaction. The sql commands between open and close are just selects.

ProcMon shows my program and my antivirus looking at the database file. It does not show my program releasing the db file after the close().

Visual Studio 2010, C#, System.Data.SQLite version 1.0.77.0, Win7

I saw a two year old bug just like this but the changelog says it's fixed.

Is there anything else I can check? Is there a way to get a list of any open commands or transactions?


New, working code:

 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);

解决方案

Encountered the same problem a while ago while writing a DB abstraction layer for C# and I never actually got around to finding out what the issue was. I just ended up throwing an exception when you attempted to delete a SQLite DB using my library.

Anyway, this afternoon I was looking through it all again and figured I would try and find out why it was doing that once and for all, so here is what I've found so far.

What happens when you call SQLiteConnection.Close() is that (along with a number of checks and other things) the SQLiteConnectionHandle that points to the SQLite database instance is disposed. This is done through a call to SQLiteConnectionHandle.Dispose(), however this doesn't actually release the pointer until the CLR's Garbage Collector performs some garbage collection. Since SQLiteConnectionHandle overrides the CriticalHandle.ReleaseHandle() function to call sqlite3_close_interop() (through another function) this does not close the database.

From my point of view this is a very bad way to do things since the programmer is not actually certain when the database gets closed, but that is the way it has been done so I guess we have to live with it for now, or commit a few changes to System.Data.SQLite. Any volunteers are welcome to do so, unfortunately I am out of time to do so before next year.

TL;DR The solution is to force a GC after your call to SQLiteConnection.Close() and before your call to File.Delete().

Here is the sample code:

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

Good luck with it, and I hope it helps

这篇关于System.Data.SQLite Close() 不释放数据库文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆