如何从 SqlDataReader 克隆数据,以可以通过方法导出的方式保留所有列和行?
How do I clone data from a SqlDataReader keeping all Columns and Rows in a way that can be exported through a method?
我目前正在尝试创建一种方法,允许我 运行 连接字符串上的任何查询,并以可读的方式为我的 ASP.Net 获取结果 return网站。因为我需要访问查询可能需要的所有行和列,所以我不能简单地 return 一个字符串或一个字符串数组。如果我 return 一个 SqlDataReader,我将无法读取方法之外的数据,因为连接已关闭。
这是我的方法目前的样子。
private SqlDataReader QueryConnectionString (string query)
{
// New SQL Connection
SqlConnection cnn;
// New Connection String
string connetionString = ConfigurationManager.ConnectionStrings["ConnectionStringName"].ConnectionString;
// Instantiate the SQL Connection with Connection String
cnn = new SqlConnection(connetionString);
// Create a SqlCommand with the input Query
SqlCommand command = new SqlCommand(query, cnn);
cnn.Open();
// Create a SqlDataReader and tie it to the query
SqlDataReader reader = command.ExecuteReader();
cnn.Close();
return reader;
}
在我的其他方法中,我会有这样的东西
SqlDataReader reader = QueryConnectionString("SELECT * FROM tTable");
lblOutput.Text = reader.GetString(0);
但是这样做给我错误
System.InvalidOperationException: 'Invalid attempt to call
CheckDataIsReady when reader is closed.'
我意识到 returning SqlDataReader 不是一个选项。我可以 return 什么数据,以便其他方法可以读取数据?
你可以试试这个
IEnumerable<IDataRecord> GetRecords()
{
using(var connection = new SqlConnection(@"..."))
{
connection.Open();
using(var command = new SqlCommand(@"...", connection);
{
using(var reader = command.ExecuteReader())
{
while(reader.Read())
{
// your code here.
yield return reader;
}
}
}
}
}
您可以return一个DataTable
,这将保留查询的列和行。考虑使用 SqlDataAdapter
而不是 SqlDataReader
。一个优点是 SqlDataAdapter
的 Fill
方法将为您打开和关闭连接。
var dt = new DataTable();
using (var da = new SqlDataAdapter(query, cnn))
{
da.Fill(dt);
}
您的完整方法可能如下所示:
private DataTable GetData(string query)
{
// New Connection String
string connetionString = ConfigurationManager.ConnectionStrings["ConnectionStringName"].ConnectionString;
// Instantiate the SQL Connection with Connection String
SqlConnection cnn = new SqlConnection(connetionString);
// declare datatable
var dt = new DataTable();
// create SqlDataAdapter
using (var da = new SqlDataAdapter(query, cnn))
{
// fill datatable
da.Fill(dt);
}
return dt;
}
然后您需要从数据表中读取。有关读取数据的方法,请参阅我的回答 here。链接答案中的方法使用 DataSetExtensions
的 Field<T>
扩展来提取数据。请看下面的例子:
// get data from your method
DataTable table = GetData("select * from MyTable");
// iterate over the rows of the datatable
foreach (var row in table.AsEnumerable()) // AsEnumerable() returns IEnumerable<DataRow>
{
var id = row.Field<int>("ID"); // int
var name = row.Field<string>("Name"); // string
var orderValue = row.Field<decimal>("OrderValue"); // decimal
var interestRate = row.Field<double>("InterestRate"); // double
var isActive = row.Field<bool>("Active"); // bool
var orderDate = row.Field<DateTime>("OrderDate"); // DateTime
}
要检查 DataTable 是否为 null/空,请参阅此 answer。它可以很简单:
if(table?.Rows?.Count() > 0) { ... }
我目前正在尝试创建一种方法,允许我 运行 连接字符串上的任何查询,并以可读的方式为我的 ASP.Net 获取结果 return网站。因为我需要访问查询可能需要的所有行和列,所以我不能简单地 return 一个字符串或一个字符串数组。如果我 return 一个 SqlDataReader,我将无法读取方法之外的数据,因为连接已关闭。
这是我的方法目前的样子。
private SqlDataReader QueryConnectionString (string query)
{
// New SQL Connection
SqlConnection cnn;
// New Connection String
string connetionString = ConfigurationManager.ConnectionStrings["ConnectionStringName"].ConnectionString;
// Instantiate the SQL Connection with Connection String
cnn = new SqlConnection(connetionString);
// Create a SqlCommand with the input Query
SqlCommand command = new SqlCommand(query, cnn);
cnn.Open();
// Create a SqlDataReader and tie it to the query
SqlDataReader reader = command.ExecuteReader();
cnn.Close();
return reader;
}
在我的其他方法中,我会有这样的东西
SqlDataReader reader = QueryConnectionString("SELECT * FROM tTable");
lblOutput.Text = reader.GetString(0);
但是这样做给我错误
System.InvalidOperationException: 'Invalid attempt to call CheckDataIsReady when reader is closed.'
我意识到 returning SqlDataReader 不是一个选项。我可以 return 什么数据,以便其他方法可以读取数据?
你可以试试这个
IEnumerable<IDataRecord> GetRecords()
{
using(var connection = new SqlConnection(@"..."))
{
connection.Open();
using(var command = new SqlCommand(@"...", connection);
{
using(var reader = command.ExecuteReader())
{
while(reader.Read())
{
// your code here.
yield return reader;
}
}
}
}
}
您可以return一个DataTable
,这将保留查询的列和行。考虑使用 SqlDataAdapter
而不是 SqlDataReader
。一个优点是 SqlDataAdapter
的 Fill
方法将为您打开和关闭连接。
var dt = new DataTable();
using (var da = new SqlDataAdapter(query, cnn))
{
da.Fill(dt);
}
您的完整方法可能如下所示:
private DataTable GetData(string query)
{
// New Connection String
string connetionString = ConfigurationManager.ConnectionStrings["ConnectionStringName"].ConnectionString;
// Instantiate the SQL Connection with Connection String
SqlConnection cnn = new SqlConnection(connetionString);
// declare datatable
var dt = new DataTable();
// create SqlDataAdapter
using (var da = new SqlDataAdapter(query, cnn))
{
// fill datatable
da.Fill(dt);
}
return dt;
}
然后您需要从数据表中读取。有关读取数据的方法,请参阅我的回答 here。链接答案中的方法使用 DataSetExtensions
的 Field<T>
扩展来提取数据。请看下面的例子:
// get data from your method
DataTable table = GetData("select * from MyTable");
// iterate over the rows of the datatable
foreach (var row in table.AsEnumerable()) // AsEnumerable() returns IEnumerable<DataRow>
{
var id = row.Field<int>("ID"); // int
var name = row.Field<string>("Name"); // string
var orderValue = row.Field<decimal>("OrderValue"); // decimal
var interestRate = row.Field<double>("InterestRate"); // double
var isActive = row.Field<bool>("Active"); // bool
var orderDate = row.Field<DateTime>("OrderDate"); // DateTime
}
要检查 DataTable 是否为 null/空,请参阅此 answer。它可以很简单:
if(table?.Rows?.Count() > 0) { ... }