![](/img/trans.png)
[英]System.ObjectDisposedException when trying to receive the data from a List
[英]Encountering ObjectDisposedException when trying to read from SQLiteDataReader
我正在嘗試通讀存儲的SQLiteDataReader
對象。 從理論上講,它“應該”工作,因為對象在被引用之前就存儲在變量中(並且直到到達參考行時才出錯),但是也許我有一個錯誤的主意。
我試圖將我的應用程序保持在整齊的分層體系結構中。 因此,每個數據庫表都具有自己的C#類以及用於選擇,插入,更新和刪除的方法。 只有數據層知道如何與數據庫通信,等等。
較早時,當我嘗試創建一個靜態SQLiteConnection
對象時,我遇到了連接問題,所有數據層類都可以引用該對象(以使其保持打開狀態並最大程度地減少開銷(如果有))。 因此,我嘗試using
塊來確保每次需要訪問數據庫時都正確處理了連接,並希望這不會導致性能問題。
因此,基本上,這是我的DatabaseConnection
類中處理基本查詢執行的方法:
public SQLiteDataReader ExecuteQuery(string sql)
{
SQLiteDataReader rdr = null;
using(SQLiteConnection conn = new SQLiteConnection(ConnectionString))
{
conn.Open();
SQLiteCommand cmd = conn.CreateCommand();
cmd.CommandText = sql;
rdr = cmd.ExecuteReader();
}
return rdr;
}
這是調用該方法的代碼。 我將以Associate
表的對象/記錄為例。
public class Associate
{
public int RowId { get; private set; }
public int Id { get; set; }
public string Name { get; set; }
private string password;
public string Password
{
get
{
return password;
}
set
{
password = Hash(value); // external password hashing method
}
}
public Associate() { } // default constructor with default values
public Associate(int id)
{
this.Id = id;
Select();
}
// select, insert, update, delete methods
private void Select() { ... }
// these are non-queries and return true/false based on success
public bool Insert() { ... }
public bool Update() { ... }
public bool Delete() { ... }
/* Method that causes the error */
public static Associate[] GetAll()
{
DatabaseConnection con = new DatabaseConnection();
SQLiteDataReader rdr = con.ExecuteQuery("SELECT id FROM Associate");
List<Associate> list = new List<Associate>();
if (rdr != null)
{
while (rdr.Read()) /* this line throws the exception */
{
int next = rdr.GetInt32(0);
list.Add(new Associate(next));
}
}
return list.ToArray();
}
}
這里的想法是,使用rdr
對象,我可以直接訪問列名,這樣,如果數據庫發生了變化,我就不必重寫一堆代碼來調整列索引( rdr["id"]
, rdr["name"]
等)
因此,我不明白的是,為什么調用方法中的rdr
會出現“對象處置”問題,因為在我引用它之前將其存儲在變量中。 我知道連接位於被調用方法的末尾,但是由於存儲了返回的結果,因此它在技術上是否應該能夠“生存”在using
塊之外?
是被配置的連接。 數據讀取器只能在連接仍然存在時讀取數據。
public SQLiteDataReader ExecuteQuery(string sql)
{
SQLiteDataReader rdr = null;
using(SQLiteConnection conn = new SQLiteConnection(ConnectionString))
{
conn.Open();
SQLiteCommand cmd = conn.CreateCommand();
cmd.CommandText = sql;
rdr = cmd.ExecuteReader();
}
// *** Connection gone at this stage ***
return rdr;
}
您的選擇是返回一個DataTable,例如
public DataTable ExecuteQuery(string sql)
{
SQLiteDataReader rdr = null;
using(SQLiteConnection conn = new SQLiteConnection(ConnectionString))
{
conn.Open();
SQLiteCommand cmd = conn.CreateCommand();
cmd.CommandText = sql;
rdr = cmd.ExecuteReader();
var dataTable = new DataTable();
dataTable.Load(rdr);
return dataTable;
}
}
否則,您可以在DatabaseConnection類中保持連接處於活動狀態:
class DatabaseConnection : IDisposable
{
private readonly IDbConnection _conn;
public DatabaseConnection()
{
_conn = new SQLiteConnection(ConnectionString);
}
public void Dispose()
{
_conn.Dispose();
}
public SQLDataReader ExecuteQuery(string sql)
{
...
}
}
// sample usage
using (var conn = new DatabaseConnection())
{
using (var reader = conn.ExecuteQuery("SELECT ...")
{
// do your work in here
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.