Description
Microsoft.Data.Sqlite keeps handle on file even after close, and pool clear
Using Microsoft.Data.Sqlite along with SQLitePCLRaw.bundle_e_sqlcipher, opening a file that's not a valid database file (throws error 26), the driver keeps the handle on the file, even in ReadOnly mode, and Pooling off.
(We want to try and perform an integrity check on our databases, and alert the user of any issues, and can't copy off the file as it stands right now, as it's in-use.)
SqliteConnectionInternal calls SqliteException.ThrowExceptionForRC(rc, _db) but the file handle doesn't look to be let go via something like sqlite3_close_v2(sqlite3 db), even on Dispose of the internal connection on Close() in the catch of the Open()? (_db.Dispose();)
using System.Data;
using Microsoft.Data.Sqlite;
Console.WriteLine("Db test");
string dbPath = "C:\\tmp\\test.db";
if (File.Exists(dbPath)) File.Delete(dbPath);
File.WriteAllText(dbPath, "this is not a database file.");
string connectionString = $"data source={dbPath};Password=12345;Mode=ReadOnly;Pooling=False";
SqliteCommand? cmd = null;
using SqliteConnection connection = new SqliteConnection(connectionString);
try
{
connection.Open(); // exception thrown here
cmd = connection.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "select count(*) from sqlite_master";
var numTables = cmd.ExecuteScalar();
bool everythingOk = (Convert.ToInt32(numTables) > 0);
Console.WriteLine($"everythingOk:{everythingOk}");
}
catch (Exception e)
{
Console.WriteLine(e);
if (e is SqliteException sqliteException)
{
if (sqliteException.SqliteErrorCode == 26) // not a db
{
if (connection.State == ConnectionState.Open) connection.Close();
SqliteConnection.ClearPool(connection);
File.Move(dbPath, dbPath + $"{DateTime.Now.Ticks}.bad"); // exception thrown here
}
}
}
finally
{
if (cmd != null)
{
cmd.Connection = null;
cmd.Dispose();
}
if (connection.State == ConnectionState.Open) connection.Close();
SqliteConnection.ClearPool(connection);
}
Include version information
Microsoft.Data.Sqlite version: 8.0.10
Target framework: .NET 8
Operating system: Win 11
SQLitePCLRaw.bundle_e_sqlcipher 2.1.10