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;
}
我希望这可以节省一些时间。
剧情简介
我有一个小型本地 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;
}
我希望这可以节省一些时间。