【发布时间】: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之前创建了数据读取器。 -
不可能。发布您声称有效的代码。我怀疑会有不同。