Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
System.Data.SQLite Close()未释放数据库文件_Sqlite_System.data.sqlite - Fatal编程技术网

System.Data.SQLite Close()未释放数据库文件

System.Data.SQLite Close()未释放数据库文件,sqlite,system.data.sqlite,Sqlite,System.data.sqlite,我在尝试删除文件之前关闭数据库时遇到问题。代码只是 myconnection.Close(); File.Delete(filename); 并且Delete抛出一个异常,该文件仍在使用中。几分钟后,我在调试器中重新尝试了Delete(),因此这不是时间问题 我有事务代码,但在Close()调用之前它根本不运行。所以我相当肯定这不是一笔公开交易。打开和关闭之间的sql命令只是选择 ProcMon显示我的程序和我的防病毒程序,查看数据库文件。它不显示我的程序在关闭()后释放db文件

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

 myconnection.Close();    
 File.Delete(filename);
并且Delete抛出一个异常,该文件仍在使用中。几分钟后,我在调试器中重新尝试了Delete(),因此这不是时间问题

我有事务代码,但在Close()调用之前它根本不运行。所以我相当肯定这不是一笔公开交易。打开和关闭之间的sql命令只是选择

ProcMon显示我的程序和我的防病毒程序,查看数据库文件。它不显示我的程序在关闭()后释放db文件

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

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

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


新的工作代码:

 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);
db.Close();
GC.Collect();//是的,真的释放数据库
布尔工作=假;
int=1;
而((尝试<4)和(!工作))
{
尝试
{
线程。睡眠(尝试*100);
删除(文件名);
工作=真实;
}
catch(ioe异常)//delete仅在锁定时抛出此
{
尝试++;
}
}
如果(!工作)
抛出新IOException(“无法关闭文件”+文件名);

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

不管怎样,今天下午我又看了一遍,我想我会努力找出它为什么要这样做,这就是我迄今为止的发现

调用
SQLiteConnection.Close()
时发生的情况是,指向SQLite数据库实例的
SQLiteConnectionHandle
被释放(以及一些检查和其他事情)。这是通过调用
SQLiteConnectionHandle.Dispose()
完成的,但是在CLR的垃圾收集器执行一些垃圾收集之前,这实际上不会释放指针。由于
SQLiteConnectionHandle
重写
CriticalHandle.ReleaseHandle()
函数调用
sqlite3\u close\u interop()
(通过另一个函数),因此不会关闭数据库

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

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

以下是示例代码:


祝你好运,我希望这会有所帮助。

不久前在为C#编写DB抽象层时遇到了同样的问题,而我从未真正找到问题所在。当您试图使用我的库删除SQLite DB时,我抛出了一个异常

不管怎样,今天下午我又看了一遍,我想我会努力找出它为什么要这样做,这就是我迄今为止的发现

调用
SQLiteConnection.Close()
时发生的情况是,指向SQLite数据库实例的
SQLiteConnectionHandle
被释放(以及一些检查和其他事情)。这是通过调用
SQLiteConnectionHandle.Dispose()
完成的,但是在CLR的垃圾收集器执行一些垃圾收集之前,这实际上不会释放指针。由于
SQLiteConnectionHandle
重写
CriticalHandle.ReleaseHandle()
函数调用
sqlite3\u close\u interop()
(通过另一个函数),因此不会关闭数据库

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

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

以下是示例代码:


祝您好运,我希望这会有所帮助。我遇到了类似的问题,我尝试了使用
GC.Collect
的解决方案,但是,如前所述,文件未锁定可能需要很长时间


我找到了一个替代解决方案,该解决方案涉及在TableAdapters中处理底层的
SQLiteCommand
s,请参阅以获取更多信息。

我遇到了类似的问题,我尝试了使用
GC.Collect
的解决方案,但如前所述,可能需要很长时间才能将文件锁定


我找到了一个替代解决方案,涉及在TableAdapters中处理底层的
SQLiteCommand
s,请参阅以获取更多信息。

在我的例子中,我创建
SQLiteCommand
对象时没有显式地处理它们

var command = connection.CreateCommand();
command.CommandText = commandText;
value = command.ExecuteScalar();
我将命令包装在一个语句中,它解决了我的问题

static public class SqliteExtensions
{
    public static object ExecuteScalar(this SQLiteConnection connection, string commandText)
    {
        using (var command = connection.CreateCommand())
        {
            command.CommandText = commandText;
            return command.ExecuteScalar();
        }
    }
}
using
语句确保即使发生异常也调用Dispose

这样执行命令就容易多了

value = connection.ExecuteScalar(commandText)
// Command object created and disposed

在我的例子中,我创建
SQLiteCommand
对象时没有显式地处理它们

var command = connection.CreateCommand();
command.CommandText = commandText;
value = command.ExecuteScalar();
我将命令包装在一个语句中,它解决了我的问题

static public class SqliteExtensions
{
    public static object ExecuteScalar(this SQLiteConnection connection, string commandText)
    {
        using (var command = connection.CreateCommand())
        {
            command.CommandText = commandText;
            return command.ExecuteScalar();
        }
    }
}
using
语句确保即使在
public static class ClearSQLiteCommandConnectionHelper
{
    private static readonly List<SQLiteCommand> OpenCommands = new List<SQLiteCommand>();

    public static void Initialise()
    {
        SQLiteConnection.Changed += SqLiteConnectionOnChanged;
    }

    private static void SqLiteConnectionOnChanged(object sender, ConnectionEventArgs connectionEventArgs)
    {
        if (connectionEventArgs.EventType == SQLiteConnectionEventType.NewCommand && connectionEventArgs.Command is SQLiteCommand)
        {
            OpenCommands.Add((SQLiteCommand)connectionEventArgs.Command);
        }
        else if (connectionEventArgs.EventType == SQLiteConnectionEventType.DisposingCommand && connectionEventArgs.Command is SQLiteCommand)
        {
            OpenCommands.Remove((SQLiteCommand)connectionEventArgs.Command);
        }

        if (connectionEventArgs.EventType == SQLiteConnectionEventType.Closed)
        {
            var commands = OpenCommands.ToList();
            foreach (var cmd in commands)
            {
                if (cmd.Connection == null)
                {
                    OpenCommands.Remove(cmd);
                }
                else if (cmd.Connection.State == ConnectionState.Closed)
                {
                    cmd.Connection = null;
                    OpenCommands.Remove(cmd);
                }
            }
        }
    }
}
static void Main(string[] args)
{
    try
    {
        var dbPath = "myTestDb.db";
        ExecuteTestCommand(dbPath);
        File.Delete(dbPath);
        Console.WriteLine("DB removed");
    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);
    }
    Console.Read();
}

private static void ExecuteTestCommand(string dbPath)
{
    using (var connection = new SQLiteConnection("Data Source=" + dbPath + ";"))
    {
        using (var command = connection.CreateCommand())
        {
            command.CommandText = "PRAGMA integrity_check";
            connection.Open();
            var reader = command.ExecuteReader();
            if (reader.Read())
                Console.WriteLine(reader.GetString(0));

            //without next line database file will remain locked
            reader.Close();
        }
    }   
}
    Reader.Close()
    connection.Close()
    GC.Collect()
    GC.WaitForPendingFinalizers()
    command.Dispose()
    SQLite.SQLiteConnection.ClearAllPools()
Con.Close();  
GC.Collect();`
GC.WaitForPendingFinalizers();
File.Delete(Environment.CurrentDirectory + "\\DATABASENAME.DB");
SQLiteConnection bc;
string sql;
var cmd = new SQLiteCommand(sql, bc);
SQLiteDataReader reader = cmd.ExecuteReader();
reader.Read();
reader.Close(); // when I added that string, the problem became solved.
SQLiteCommand insertCommand = connection.CreateCommand();
try {
    // some insert parameters
    insertCommand.ExecuteNonQuery();
} catch (SQLiteException exception) {
    insertCommand.Cancel();
    insertCommand.Dispose();
}
dbConnection.Close();
System.Data.SQLite.SQLiteConnection.ClearAllPools();

GC.Collect();
GC.WaitForPendingFinalizers();

File.Delete(Environment.CurrentDirectory + "\\DATABASENAME.DB");