I had the same problem using datasets / table adapters generated using the constructor supplied with System.Data.Sqlite.dll version 1.0.82.0 - after closing the connection, we were not able to read the database file using System.IO.FileStream . I managed the connection and tables correctly, and I did not use the connection pool.
According to my first search queries (like this and this thread ), which seemed to be a problem in the library itself - either objects that were not correctly released, and / or problems with the pool (which I do not use).
After reading your question, I tried to replicate the problem using only SQLiteCommand objects, and found that the problem occurs when you do not destroy them. Update 2012-11-27 19:37 UTC : this ticket is confirmed for System.Data. SQLite, in which the developer explains that "all SQLiteCommand and SQLiteDataReader objects associated with the connection [must be] correctly placed."
Then I returned to the generated table adapters, and I saw that the implementation of the Dispose method was not implemented, so in fact the created commands were not deleted. I implemented this, taking care of recycling all the commands, and I have no problem.
Here's the code in C #, hope this helps. Note that the code is converted from original to 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(); } } } }
Update 2013-07-05 17:36 UTC gorogm's answer highlights two important things:
according to changelog on the official site System.Data.SQLite, starting from version 1.0.84.0, the above code is not required, since the library will take care of this. I have not 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(); }
on the implementation of the Dispose TableAdapter : itβs better to put this in a partial class so that the regeneration of the data set will not affect this code (and any additional code you may need to add).
edymtt Oct 01 2018-12-12T00: 00Z
source share