【问题标题】:Why does the DataTableReader lose its data when using MySqlDataAdapter?为什么 DataTableReader 在使用 MySqlDataAdapter 时会丢失数据?
【发布时间】:2014-11-20 12:53:30
【问题描述】:

我有以下方法:

public DataTableReader Get<T>(string sql, T[] parameters, CommandType commandType = CommandType.Text)
{
    DataTableReader result;
    using (var connection = new MySqlConnection(_connectionString))
    {
        using (var command = new MySqlCommand())
        {
            command.CommandType = commandType;
            command.CommandText = sql;
            command.Connection = connection;
            if (parameters != null)
            {
                command.Parameters.AddRange(parameters);
            }
            using (var adapter = new MySqlDataAdapter())
            {
                adapter.SelectCommand = command;
                using (var dataTable = new DataTable())
                {
                    adapter.Fill(dataTable);
                    result = dataTable.CreateDataReader();
                } // result contains data here
            } // result "loses" data here
        }
    }
    return result;
}

但是,当我到达我评论过的有关丢失数据的行时,DataTableReader 是空的。如果我在它上面的行中放置一个断点(我已经评论结果包含数据)结果确实包含结果。

发生了什么事?这几乎就像是作为参考传递了一些东西。

编辑:我可能应该注意到,我有相同的代码来连接到 SQL Server,上面的 MySQL 特定类的任何实例都替换为 SqlCommand,SqlDataAdapter .这一切似乎都奏效了。

根据要求,这里是MSSql的对应方法:

public virtual DataTableReader Get(string sql, SqlParameter[] parameters, CommandType commandType = CommandType.Text)
{
    DataTableReader result;
    using (var sqlConnection = new SqlConnection(_coreConnectionString))
    {
        using (var myCommand = new SqlCommand())
        {
            myCommand.CommandType = commandType;
            myCommand.CommandText = sql;
            myCommand.Connection = sqlConnection;
            if (parameters != null)
            {
                myCommand.Parameters.AddRange(parameters);
            }
            using (var myAdapter = new SqlDataAdapter())
            {
                myAdapter.SelectCommand = myCommand;
                using (var myDataTable = new DataTable())
                {
                    myAdapter.Fill(myDataTable);
                    result = myDataTable.CreateDataReader();
                }
            }
        }
    }
    return result;
}

我更新了 top 方法以更快地返回 DataReader:

public DataTableReader Get<T>(string sql, T[] parameters, CommandType commandType = CommandType.Text)
{
    using (var connection = new MySqlConnection(_connectionString))
    {
        using (var command = new MySqlCommand())
        {
            command.CommandType = commandType;
            command.CommandText = sql;
            command.Connection = connection;
            if (parameters != null)
            {
                command.Parameters.AddRange(parameters);
            }
            using (var adapter = new MySqlDataAdapter())
            {
                adapter.SelectCommand = command;
                using (var dataTable = new DataTable())
                {
                    adapter.Fill(dataTable);
                    var reader = dataTable.CreateDataReader();
                    return reader;
                }
            }
         }
     }
 }

我已经将变量的赋值留在了 return 语句的另一行,这样我就可以验证 reader 正在被填充。但是,当它返回到调用方法时,那里什么都没有。

调用Get() 的代码是var dt = _dbHelper.Get(sql, parameters),我知道该sql 可以工作,因为在它返回之前,对象中有我期望的数据。

更多编辑:我一直在做更多的挖掘工作,因为这真的让我很烦。首先,如果我使用var reader = dataTable.Copy().CreateDataReader();,则返回数据。但是当然这会创建一个新版本的对象,所以这可能会导致内存问题。

其次(这真的让我很烦)MySqlDataAdapter 使用的Fill() 方法不是它自己的实现。它使用来自DbDataAdapter 的实现(它和SqlDataAdapter 都继承自)。那怎么不一样呢?

【问题讨论】:

  • 因为你正在处理DataTable
  • @DanielA.White 使用数据适配器填充 DataTable 意味着您拥有数据的本地副本。进一步的访问不依赖于用于执行填充的数据库连接/命令/...。
  • @DanielA.White 连接由 adapter.Fill() 方法打开和关闭。在我创建数据读取器(下面的行)时,连接已经关闭。
  • @SriramSakthivel 但我已经在处理 DataTable 之前创建了数据读取器。
  • 不可能。发布您声称有效的代码。我怀疑会有不同。

标签: c# mysql


【解决方案1】:

在这一行:

using (var myDataTable = new DataTable())
                {
                    myAdapter.Fill(myDataTable);
                    result = myDataTable.CreateDataReader();
                }

使用 using 你正在这样做,当代码从 using 中退出时,DataTable 被释放,然后你会得到空数据。

尝试声明 DataTable 并在最后关闭它。也许使用try/catch/finally 块是一个很好的方法,最后你可以添加dispose。

希望对你有帮助

【讨论】:

  • 我不确定,但可能 Fill 方法在 MySqlDataAdapter 中的工作方式与它在 SqlDataAdapter 中的工作方式不同。如果在 CreateDataReader() 之后调用 Fill 会发生什么?
  • 另外,到那时我已经填充了数据表(这是标准的 .NET 数据表),所以此时适配器发生了什么并不重要,它还没有被处理. DataTableDataTableReader 都是标准的 .NET,不是 MySQL 特定的。
  • 如果我在CreateDatareader() 之后运行Fill() 方法,结果是空的,因为数据表是空的。
  • MySqlDataAdapter 使用的Fill 方法和SqlDataAdapter 使用的方法是一样的(见我原问题文末)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-10
  • 1970-01-01
  • 2021-10-06
  • 1970-01-01
  • 1970-01-01
  • 2013-10-17
相关资源
最近更新 更多