'Microsoft.Data.Sqlite' 意外行为

'Microsoft.Data.Sqlite' unexpected behaviour

我的代码中有一个方法,它将 sqlite3 db 初始化到指定目录,如以下代码片段所示:

using System;
using System.IO;
using Microsoft.Data.Sqlite;

namespace test
{
    public static class DatabaseUtils
    {
        public static void InitializeDatabase(string directoryPath)
        {
            if (!Directory.Exists(directoryPath))
            {
                throw new Exception();
            }

            string sqliteFile = Path.Combine(Path.GetFullPath(directoryPath), "test.sqlite3");

            if (File.Exists(sqliteFile))
            {
                throw new Exception();
            }
            else
            {
                try
                {
                    File.Create(sqliteFile).Dispose();

                    using (SqliteConnection connection = new SqliteConnection($"Data Source={sqliteFile};Mode=ReadWrite"))
                    {
                        connection.Open();
                        
                        using (SqliteCommand command = new SqliteCommand())
                        {
                            command.Connection = connection;
                            command.CommandText = "DROP TABLE IF EXISTS MyTable; CREATE TABLE MyTable (Primary_Key INTEGER PRIMARY KEY, Text_Entry NVARCHAR(2048) NULL)";
                            command.ExecuteNonQuery();
                        }

                        connection.Close();
                    }
                }
                catch (Exception)
                {
                    throw;
                }
            }
        }
    }
}

案例一: 第一次调用此方法时,一切都按预期进行。 这意味着 => 数据库文件是使用代码中指定的 table(MyTable) 创建的。

案例二: 第二次调用此方法时,手动删除数据库文件后, 创建数据库文件时没有在代码中指定 table(MyTable) 并发生以下错误 => SQLite Error 8: 'attempt to write a readonly database'

在我看来,好像在第一个 运行 之后没有正确处理与数据库的连接,或者在第一个 运行 期间创建的数据库以某种方式保留在内存中。

预期行为: 方法应创建指定 tables 的 sqlite 数据库文件,每次调用时,当满足上述条件时。

使用的软件包: "Microsoft.Data.Sqlite, 版本 6.0.2", "PowerShellStandard.Library,版本 5.1.0"

目标框架: .NET 6

值得一提: 将 'File.Create()' 方法替换为 'Mode=ReadWriteCreate' ConnectionString 时,手动删除后不会第二次创建文件。仅在第一种方法期间 运行.

编辑: 已将 'Microsoft.Data.Sqlite' 换成 'System.Data.SQLite.Core' 现在该方法每次都按预期工作。

我想这可能是 'Microsoft.Data.Sqlite' 中的一个 BUG,或者我只是遗漏了这两个库之间的一个重要区别。

如果能得到 MSFT 开发人员关于我做错了什么的官方答复,那就太好了。

打开和关闭连接2次可能出现问题: 你可以这样试试吗:

    using (SQLiteConnection connection = new SQLiteConnection($"Data Source={SqliteFile};Mode=ReadWrite"))
    {
        using (SQLiteCommand command = new SQLiteCommand())
        {
            command.Connection = connection;
            command.CommandText = "DROP TABLE IF EXISTS MyTable; CREATE TABLE MyTable (Primary_Key INTEGER PRIMARY KEY, Text_Entry NVARCHAR(2048) NULL)";
            command.ExecuteNonQuery();
        }
    }

啊好的,我错过了一部分。对我来说,它总是这样工作的(简而言之):

private SQLiteConnection OpenDataBase(string dataBasePath)
{
    SQLiteConnection connection = new SQLiteConnection($@"Data Source = {dataBasePath}; Version = 3; New = True; Compress = True; ");
    connection.Open();
    return connection;
}

public void CreateTable(string dataBasePath)
{
    using (SQLiteConnection? connection = OpenDataBase(dataBasePath))
    {
        string create = "DROP TABLE IF EXISTS MyTable; CREATE TABLE MyTable (Primary_Key INTEGER PRIMARY KEY, Text_Entry NVARCHAR(2048) NULL)"; ;
        using (SQLiteCommand command = new SQLiteCommand(create, connection))
        {
            command.ExecuteNonQuery();
        }
    }
}

在 github 中深入挖掘之后,我找到了我最初问题的实际答案。有一个名为 'connection pooling'feature,它导致了我在问题中描述的 'Unexpected behaviour'。

禁用此功能,请将'Pooling=False'添加到ConnectionString,或调用'SqliteConnection.ClearAllPools()' 在你想要处理连接的地方(using 语句是不够的)。