简体   繁体   English

尝试从SQLiteDataReader读取时遇到ObjectDisposedException

[英]Encountering ObjectDisposedException when trying to read from SQLiteDataReader

I am trying to read through a stored SQLiteDataReader object. 我正在尝试通读存储的SQLiteDataReader对象。 In theory, it "should" work because the object is stored in a variable before it is referenced (and doesn't hit an error until the reference line is reached), but maybe I have the wrong idea. 从理论上讲,它“应该”工作,因为对象在被引用之前就存储在变量中(并且直到到达参考行时才出错),但是也许我有一个错误的主意。

I'm trying to keep my application in a neatly layered architecture. 我试图将我的应用程序保持在整齐的分层体系结构中。 So, each database table having its own C# class with its own methods for select, insert, update, and delete; 因此,每个数据库表都具有自己的C#类以及用于选择,插入,更新和删除的方法。 only the data layer knows how to communicate with the database, etc. 只有数据层知道如何与数据库通信,等等。

I was running into connection issues earlier when I tried to make one static SQLiteConnection object that all the data layer classes could reference (so as to keep it open and minimize overhead, if any). 较早时,当我尝试创建一个静态SQLiteConnection对象时,我遇到了连接问题,所有数据层类都可以引用该对象(以使其保持打开状态并最大程度地减少开销(如果有))。 So I'm trying to go with the using block to make sure the connection is properly disposed each time I need to access the database, and hoping that this won't cause performance issues. 因此,我尝试using块来确保每次需要访问数据库时都正确处理了连接,并希望这不会导致性能问题。

So basically, here is the method in my DatabaseConnection class that handles basic query execution: 因此,基本上,这是我的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;
}

And here is the code that calls that method. 这是调用该方法的代码。 I'll use an object/record of the Associate table as an example. 我将以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();
    }
}

The idea here is that using the rdr object, I can access the column names directly so that if the database ever changes, I won't have to rewrite a bunch of code to adjust for the column indices ( rdr["id"] , rdr["name"] , etc.) 这里的想法是,使用rdr对象,我可以直接访问列名,这样,如果数据库发生了变化,我就不必重写一堆代码来调整列索引( rdr["id"]rdr["name"]等)

So what I don't understand is why rdr in the calling method is having "object disposed" issues because it's stored in a variable before I reference it. 因此,我不明白的是,为什么调用方法中的rdr会出现“对象处置”问题,因为在我引用它之前将其存储在变量中。 I know the connection is disposed at the end of the called method, but since the returned result is stored, shouldn't it technically be able to "survive" outside the using block? 我知道连接位于被调用方法的末尾,但是由于存储了返回的结果,因此它在技术上是否应该能够“生存”在using块之外?

It is the connection that got disposed. 是被配置的连接。 The data reader can only read data while the connection still exists. 数据读取器只能在连接仍然存在时读取数据。

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;
}

Your options are to either return a DataTable, eg 您的选择是返回一个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;
    }
}

otherwise, you could keep the connection alive inside the DatabaseConnection class: 否则,您可以在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.

相关问题 尝试从List接收数据时System.ObjectDisposedException - System.ObjectDisposedException when trying to receive the data from a List 尝试上传文件时出现ObjectDisposedException - ObjectDisposedException when trying to upload a file SQLiteDataReader.read()清空结果? - SQLiteDataReader.read() empties results? 尝试列出对象时出现System.ObjectDisposedException - System.ObjectDisposedException when trying to list an object 尝试将文件保存到DbContext时抛出ObjectDisposedException - ObjectDisposedException thrown when trying to save files to a DbContext System.ObjectDisposedException 尝试访问 DataContext 时 - System.ObjectDisposedException when trying to access DataContext 尝试传递 id 时出现 ASP.NET MVC ObjectDisposedException - ASP.NET MVC ObjectDisposedException when trying to pass id 遇到 System.IndexOutOfRangeException:尝试显示数据库中两个表中的数据时 - Encountering a System.IndexOutOfRangeException: when trying to display data from two tables in a database 尝试以自己的using语句访问MemoryStream时,MemoryStream抛出ObjectDisposedException - MemoryStream throws ObjectDisposedException when trying to access it in its own using statement 尝试在请求管道内写入数据库时​​出现ObjectDisposedException - ObjectDisposedException when trying to write to database inside request pipeline
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM