更新时间:2022-12-31 12:58:09
我不得不使用带有附带设计器生成数据集/ TableAdapter的同样的问题 System.Data.Sqlite.dll
1.0.82.0版本 - 关闭我们无法读取使用 System.IO.FileStream
数据库文件的连接之后。我是正确处理两者的连接和TableAdapter的,我并没有使用连接池。
I had the same problem using the datasets/tableadapters generated with the designer shipped with System.Data.Sqlite.dll
version 1.0.82.0 -- after closing the connection we were unable to read the database file using System.IO.FileStream
. I was disposing correctly both connection and tableadapters and I was not using connection pooling.
据我的第一个搜索(例如this和this这似乎在图书馆本身的问题线程) - 无论是对象不正确地释放和/或池的问题(我不使用)
According to my first searches (for example this and this thread) that seemed a problem in the library itself -- either objects not correctly released and/or pooling issues (which I don't use).
阅读您的问题后,我试图复制使用问题只SQLiteCommand对象,我发现,问题就出现了,当你不处理它们。 更新2012年11月27日19:37 UTC :这是由这对于System.Data.SQLite票,其中开发人员解释说,与连接相关联的所有的SQLiteCommand和SQLiteDataReader对象[应]妥善处理。
After reading your question I tried to replicate the problem using only SQLiteCommand objects and I found that the problem arises when you don't dispose them. Update 2012-11-27 19:37 UTC: this is further confirmed by this ticket for System.Data.SQLite, in which a developer explains that "all SQLiteCommand and SQLiteDataReader objects associated with the connection [should be] properly disposed".
我再重新打开生成的TableAdapter的,我看到,没有了的Dispose
方法的实现 - 所以其实创建的命令并未处理。我实现它,以处理所有的命令照顾,和我有没有问题。
I then turned back on the generated TableAdapters and I saw that there was no implementation of the Dispose
method -- so in fact the created commands were not disposed. I implemented it, taking care of disposing all the commands, and I have got no problem.
下面是在C#中code,希望这有助于。请注意,code都在Visual Basic中中的原来的转换,所以我们期待一些转换错误。
Here's the code in C#, hope this helps. Please note that the code is converted from the original in Visual Basic, so expect some conversion errors.
//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年7月5日17:36 UTC gorogm的回答突出了两个重要的事情
Update 2013-07-05 17:36 UTC gorogm's answer highlights two important things:
根据的changelog 在官方网站System.Data.SQLite,从版本1.0.84.0上述code首发应该没有必要,因为库会处理这件事。我没有测试过这一点,但在最坏的情况下,你只需要这个片段:
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:
//In Table Adapter
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
this.Adapter.Dispose();
}
有关的的TableAdapter
的的Dispose
调用的实现:它是更好地把这个在部分类,让数据恢复不影响本code(以及任何额外的code,你可能需要添加)。
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).