读取器关闭时无效的读取尝试

Cha*_*amp 4 c# mysql database datareader

我的应用程序有一个通用的数据库类,在该类中我有一个函数

public MySqlDataReader getRecord(string query)
        {
            MySqlDataReader reader;
            using (var connection = new MySqlConnection(connectionString))
            {
                connection.Open();
                using (var cmd = new MySqlCommand(query, connection))
                {

                    reader = cmd.ExecuteReader();
                    return reader;

                }
            }

            return null;
        }
Run Code Online (Sandbox Code Playgroud)

以及我使用的页面后面的代码

String sql = "SELECT * FROM `table`";
MySqlDataReader dr = objDB.getRecord(sql);
if (dr.Read())
{
   // some code goes hear
} 
Run Code Online (Sandbox Code Playgroud)

并且我在读取器关闭时无效尝试读取时出错.

我知道在数据库连接关闭后访问读者是不可能的机器人我正在寻找一个不需要在代码隐藏中改变的解决方法

编辑:我将解决读者被分配给其他对象(类似于读者)并返回该对象的解决方案,因此我无需在所有应用程序页面中进行更改

Ale*_*lex 9

您可以将查询结果加载到内存中,然后关闭连接并仍然返回IDataReader按预期工作的结果.请注意,这会花费内存.

public IDataReader getRecord(string query)
    {
        MySqlDataReader reader;
        using (var connection = new MySqlConnection(connectionString))
        {
            connection.Open();
            using (var cmd = new MySqlCommand(query, connection))
            {

                reader = cmd.ExecuteReader();
                var dt = new DataTable();
                dt.Load( reader );
                return dt.CreateDataReader();
            }
        }

        return null;
    }
Run Code Online (Sandbox Code Playgroud)

在来电者中:

String sql = "SELECT * FROM `table`";
var dr = objDB.getRecord(sql); // or DataTableReader dr = ...
if (dr.Read())
{
    // some code goes here
} 
Run Code Online (Sandbox Code Playgroud)

  • @esskar这是提问者问题的可行解决方案(他已经要求一个不需要对呼叫者进行重大更改的解决方案).我明确**明确表示会增加内存需求.总之,我不必告诉你我对你的看法. (17认同)
  • 旁注:如果你*在你的数据库中拥有整个Universe,*和*你有一个可以访问它的查询,我*真的*想跟你说话.SQL是声明性的,应该可以轻松搞清楚一些棘手的东西.你有没有试过`选择姓名='Amelia Earhart'的人或类似的地方? (5认同)
  • -1表示可能将整个Universe加载到内存中. (2认同)

Zde*_*vic 5

当您的通话范围using (var connection = new MySqlConnection(connectionString)) 结束时,连接将被关闭.

但是,您仍然根据该连接返回读者.一旦您尝试在调用方法中使用它,您将收到错误,因为无法使用关闭的连接.

此外,您的方法被调用,GetRecord但它返回一个读者.

其中一个选项是这样做:

public void processQuery(string query, Action<MySqlDataReader> fn)
{
    using (var connection = new MySqlConnection(connectionString))
    {
        connection.Open();
        using (var cmd = new MySqlCommand(query, connection))
        {
            using (var reader = cmd.ExecuteReader())
            {
               fn(reader);
            }
        }
    }
}


// caller
String sql = "SELECT * FROM `table`";
objDB.procesQuery(sql, dr => {
    if (dr.Read())
    {
       // some code goes here
    } 
});
Run Code Online (Sandbox Code Playgroud)

您创建一个"类似于阅读器"的对象的想法,因此您不必更改调用者,将无法工作:返回的对象需要包含阅读器和打开的连接,以便您可以使用阅读器.这意味着您必须关闭调用者中的连接.在最好的情况下,调用者需要修改如下:

String sql = "SELECT * FROM `table`";
using (MyWrapper wr = objDB.getRecord(sql))
{
   if (wr.Reader.Read())
   {
      // some code goes here
   } 
}
Run Code Online (Sandbox Code Playgroud)

您不会节省那么多工作,但是using由于连接泄漏,调用者中的一个丢失语句将导致您的应用程序在一段时间后无法正常工作.