将数据存储到SqlDataReader时出现问题。当我分配sdr变量时,在connection.close()的位置,sdr变量变空。为什么呢?
string strConnection = ConfigurationManager.ConnectionStrings["dbconn"].ConnectionString;
SqlDataReader sdr = null;
using (SqlConnection connection = new SqlConnection(strConnection))
{
connection.Open();
using (SqlCommand cmd = new SqlCommand("GetProducts", connection))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
sdr = cmd.ExecuteReader();
}
connection.Close();
}
return (sdr);
答案 0 :(得分:3)
您需要在调用Read:
的循环中迭代读取器while(sdr.Read())
{
var someValue = sdr["SomeValue"]; //Where SomeValue is the column name you're expecting from the DB
}
所有ExecuteReader都会这样做,它是否会向您返回一个DataReader对象,但是您需要遍历返回的每一行并从中提取值。如果您想一次性完成所有操作,可以使用SqlDataAdapter:
var adapter = new SqlDataAdapter(command);
var table = new DataTable();
adapter.Fill(table);
答案 1 :(得分:3)
在迭代DataReader时,您需要一个开放且活动的连接。如果在返回数据读取器之前关闭它,它将无法工作。我通常做的就是将DataReader变成IEnumerable,如下所示:
public IEnumerable<IDataRecord> GetProductsFromDB()
{
string strConnection = ConfigurationManager.ConnectionStrings["dbconn"].ConnectionString;
using (SqlConnection connection = new SqlConnection(strConnection))
using (SqlCommand cmd = new SqlCommand("GetProducts", connection))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
connection.Open();
using (var sdr = cmd.ExecuteReader())
{
while (sdr.Read())
{
yield return sdr;
}
}
}
}
请注意,我也改变了一下顺序:等待尽可能长时间打开连接,然后在每个连接旁边放置连接和命令,以避免这么多嵌套。
这种模式为您编写数据访问代码的方式开辟了一个全新的世界,因为现在突然您的原始SQL查询和存储过程调用与linq-to-objects运算符一起工作。你可以这样做很酷:
foreach (var product in GetProductsFromDB()
.Select(i => CreateProductFromDataRow(i))
.Where(p => p.IsOnSale()) )
{
// do something with products that are on sale
}