我曾经遇到同样的问题,使用与
System.Data.Sqlite.dll
版本 1.0.82.0 一起提供的设计器生成的数据集/表适配器后,在关闭连接后,我们无法使用
System.IO.FileStream
读取数据库文件。 我正确地处理了连接和表适配器的释放,并且没有使用连接池。
根据我的首次搜索(例如
this 和
this thread),似乎这是库本身的问题,可能是对象未正确释放和/或池问题(我不使用)。
阅读您的问题后,我尝试使用仅 SQLiteCommand 对象来复制问题,发现当您不处理它们时,问题会出现。{Update 2012-11-27 19:37 UTC}:
这个票证进一步证实了这一点,对于System.Data.SQLite,其中一个开发人员解释说,“与连接相关的所有SQLiteCommand和SQLiteDataReader对象都应该正确处理”。
然后,我重新启用了生成的TableAdapters,并发现没有实现Dispose方法--因此,创建的命令没有被处理。 我实现了它,注意处理所有命令,就没有问题了。
以下是C#代码,希望能帮到您。请注意,代码是从
Visual Basic中的原始代码转换而来,因此可能会有一些转换错误。
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
Common.DisposeTableAdapter(disposing, _adapter, _commandCollection);
}
public static class Common
{
public static void DisposeTableAdapter(
bool disposing,
System.Data.SQLite.SQLiteDataAdapter adapter,
IEnumerable<System.Data.SQLite.SQLiteCommand> commandCollection)
{
if (disposing) {
DisposeSQLiteTableAdapter(adapter);
foreach (object currentCommand_loopVariable in commandCollection)
{
currentCommand = currentCommand_loopVariable;
currentCommand.Dispose();
}
}
}
public static void DisposeSQLiteTableAdapter(
System.Data.SQLite.SQLiteDataAdapter adapter)
{
if (adapter != null) {
DisposeSQLiteTableAdapterCommands(adapter);
adapter.Dispose();
}
}
public static void DisposeSQLiteTableAdapterCommands(
System.Data.SQLite.SQLiteDataAdapter adapter)
{
foreach (object currentCommand_loopVariable in {
adapter.UpdateCommand,
adapter.InsertCommand,
adapter.DeleteCommand,
adapter.SelectCommand})
{
currentCommand = currentCommand_loopVariable;
if (currentCommand != null) {
currentCommand.Dispose();
}
}
}
}
更新时间 2013-07-05 17:36 UTC gorogm 的回答 强调了两个重要的事情:
according to the changelog on the official site of System.Data.SQLite, starting from version 1.0.84.0 the above code should not be needed, since the library takes care of this. I haven't tested this, but in the worst case you only need this snippet:
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
this.Adapter.Dispose();
}
about the implementation of the Dispose
call of the TableAdapter
: it is is better to put this in a partial class, so that a dataset regeneration does not affected this code (and any additional code you may need to add).