SQLiteDataReader 似乎保持数据库连接打开

SQLiteDataReader Appears to be Holding DB Connection Open

剧情简介

我有一个小型本地 SQLite 数据库,其中包含一组用于填充 ComboBoxList 的记录。列表已填充,数据库连接已释放。未观察到数据库锁定问题。

然后,当从列表中选择一条记录时,将检索该记录并用于填充 LocalDBInstallRecord 对象。但是,填充对象后,数据库连接似乎保持打开状态并阻止任何进一步访问。

代码

    public LocalDBInstallRecord GetRecord(string recordID)
    {
        LocalDBInstallRecord lir = new LocalDBInstallRecord();
        string query = "SELECT * FROM InstallationRecords WHERE RecordID = " + recordID;

        using (SQLiteConnection localDBConnection = new SQLiteConnection(ConnectionStr))
        {
            localDBConnection.Open();
            using (SQLiteCommand cmd = new SQLiteCommand(query, localDBConnection))
            {
                using (SQLiteDataReader rdr = cmd.ExecuteReader(CommandBehavior.KeyInfo))
                {
                    while (rdr.Read())
                    {
                        lir.RecordID = (uint)rdr.GetInt32(rdr.GetOrdinal("RecordID"));
                        lir.DateCreated = rdr.GetDateTime(rdr.GetOrdinal("DateCreated"));
                        lir.Model = CheckDBNull(rdr, "Model");
                        lir.SCFirmwareVer = CheckDBNull(rdr, "SCFirmwareVer");
                        lir.DispFirmwareVer = CheckDBNull(rdr, "DispFirmwareVer");
                        lir.UCCFirmwareVer = CheckDBNull(rdr, "UCCFirmwareVer");
                        lir.Title = CheckDBNull(rdr, "Title");
                        lir.FOC = rdr.GetBoolean(rdr.GetOrdinal("FOC"));
                        lir.MCManufacturer = CheckDBNull(rdr, "MCManufacturer");
                        lir.MCType = CheckDBNull(rdr, "MCType");
                        lir.RailConvertor = CheckDBNull(rdr, "RailConvertor");
                        lir.PlantID = CheckDBNull(rdr, "PlantID");
                        lir.PlantOwner = CheckDBNull(rdr, "PlantOwner");
                        lir.PlantOwnerID = CheckDBNull(rdr, "PlantOwnerID");
                        lir.BoomLength = rdr.GetFloat(rdr.GetOrdinal("BoomLength"));
                        lir.ArticLength = rdr.GetFloat(rdr.GetOrdinal("ArticLength"));
                        lir.DipperLength = rdr.GetFloat(rdr.GetOrdinal("DipperLength"));
                        lir.MachineRecord = ReadDBBlob(rdr, "MachineRecord");
                        lir.DutyRecord = ReadDBBlob(rdr, "DutyRecord");
                        lir.CalibRecord = ReadDBBlob(rdr, "CalibRecord");
                    }
                }
            }
        }
        return lir;
    }

调用函数...

CheckDBNull

    private static string CheckDBNull(SQLiteDataReader rdr, string col)
    {
        string str = null;

        if (!rdr.IsDBNull(rdr.GetOrdinal(col)))
            str = rdr.GetString(rdr.GetOrdinal(col));

        return str;
    }

ReadDBBlob

    private static byte[] ReadDBBlob(SQLiteDataReader rdr, string col)
    {
        byte[] data = null;
        if (!rdr.IsDBNull(rdr.GetOrdinal(col)))
        {
            SQLiteBlob blob = rdr.GetBlob(rdr.GetOrdinal(col), true);
            data = new byte[blob.GetCount()];
            blob.Read(data, blob.GetCount(), 0);
        }
        return data;
    }

我的想法

我确定有更简单的方法来加载对象,但这不是问题...

我认为数据库连接保持打开状态是因为无法彻底处理 SQLiteDataReader。我怀疑这个函数中的某些东西(在 LocalDBInstallRecord 对象中)已经通过引用获取了一个对象。我只是看不到什么。

我试过不访问记录中的 DateTime 对象,但事实并非如此。

在这种情况下,我应该使用不同的方法来访问数据库吗?

非常感谢任何建议,我认为它需要一双新的眼睛。谢谢

进一步研究... 我发现如果我尝试使用另一个工具使用 SQLite 数据库,而 GetRecord() 函数持有 reader,我能够读取数据库,但不能写入。我收到来自“DB Browser SQLite”应用程序的数据库锁定 (RELEASE 'RESTOREPOINT';) 错误消息。但我认为那只是因为它正在等待 reader 发布。

问题出在函数 ReadDBBlob 中。 SQLiteBlob 是 IDisposable 的,它的使用没有封装在 using 子句中。结果,SQLiteBlob 没有被处理掉,它保留了 reader 并因此保持连接打开...

新建 ReadDBBlob

    private static byte[] ReadDBBlob(SQLiteDataReader rdr, string col)
    {
        byte[] data = null;
        if (!rdr.IsDBNull(rdr.GetOrdinal(col)))
        {
            using (SQLiteBlob blob = rdr.GetBlob(rdr.GetOrdinal(col), true))
            {
                data = new byte[blob.GetCount()];
                blob.Read(data, blob.GetCount(), 0);
            }
        }
        return data;
    }

我希望这可以节省一些时间。