我在使用System.Data.Sqlite.dll 1.0.82.0 版附带的设计器生成的数据集/表格适配器时遇到了同样的问题——关闭连接后,我们无法使用System.IO.FileStream 读取数据库文件。我正确地处理了连接和表格适配器,但我没有使用连接池。
根据我的第一次搜索(例如this 和this thread),库本身似乎存在问题——对象未正确释放和/或池问题(我不使用)。
阅读您的问题后,我尝试仅使用 SQLiteCommand 对象来复制问题,但我发现当您不处置它们时会出现问题。 更新 2012-11-27 19:37 UTC:this ticket 进一步证实了 System.Data.SQLite,其中开发人员解释说“所有 SQLiteCommand 和与连接关联的 SQLiteDataReader 对象 [应该] 正确处理”。
然后我打开生成的 TableAdapters,我看到没有实现 Dispose 方法——所以实际上创建的命令没有被释放。我实现了它,负责处理所有命令,我没有问题。
这是 C# 中的代码,希望对您有所帮助。请注意,代码是从original in Visual Basic 转换而来的,因此可能会出现一些转换错误。
//In Table Adapter
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
Common.DisposeTableAdapter(disposing, _adapter, _commandCollection);
}
public static class Common
{
/// <summary>
/// Disposes a TableAdapter generated by SQLite Designer
/// </summary>
/// <param name="disposing"></param>
/// <param name="adapter"></param>
/// <param name="commandCollection"></param>
/// <remarks>You must dispose all the command,
/// otherwise the file remains locked and cannot be accessed
/// (for example, for reading or deletion)</remarks>
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's answer 强调了两件重要的事情:
-
根据 System.Data.SQLite 官方网站上的changelog,从版本 1.0.84.0 开始,应该不需要上面的代码,因为库会处理这个问题。我没有测试过这个,但在最坏的情况下你只需要这个 sn-p:
//In Table Adapter
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
this.Adapter.Dispose();
}
关于TableAdapter 的Dispose 调用的实现:最好将其放在部分类中,这样数据集重新生成不会影响此代码(以及您可能使用的任何其他代码)需要补充)。