背景:我从数据库中获取了一堆字符串,现在想要返回它们。传统上,代码会是这样的:
public List<string> GetStuff(string connectionString)
{
List<string> categoryList = new List<string>();
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
string commandText = "GetStuff";
using (SqlCommand sqlCommand = new SqlCommand(commandText, sqlConnection))
{
sqlCommand.CommandType = CommandType.StoredProcedure;
sqlConnection.Open();
SqlDataReader sqlDataReader = sqlCommand.ExecuteReader();
while (sqlDataReader.Read())
{
categoryList.Add(sqlDataReader["myImportantColumn"].ToString());
}
}
}
return categoryList;
}
但是我想消费者可能会想要遍历这些项目,而且并不在意其他的东西,我不想将自己局限于一个列表,如果我返回 IEnumerable 就比较好/灵活。因此,我考虑使用“yield return”类型的设计来处理这个问题……就像这样:
public IEnumerable<string> GetStuff(string connectionString)
{
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
string commandText = "GetStuff";
using (SqlCommand sqlCommand = new SqlCommand(commandText, sqlConnection))
{
sqlCommand.CommandType = CommandType.StoredProcedure;
sqlConnection.Open();
SqlDataReader sqlDataReader = sqlCommand.ExecuteReader();
while (sqlDataReader.Read())
{
yield return sqlDataReader["myImportantColumn"].ToString();
}
}
}
}
现在我正在更深入地了解yield(像这样的网站上... msdn似乎没有提到这一点),它显然是一种惰性评估器,保留填充程序的状态,预期有人要求下一个值,然后仅在运行时直到返回下一个值。
在大多数情况下,这似乎很好,但对于数据库调用来说,这听起来有点危险。 作为一个有些牵强的例子,如果有人要求从我从数据库中调用的IEnumerable,并完成其中一半,然后陷入循环......据我所见,我的数据库连接将永远保持打开状态。
如果迭代器没有完成,听起来有些麻烦......我错过了什么吗?
Dispose
,就是安全的。请参见我下面的帖子。 - tofi9SqlDataReader
实现了IDisposable
接口,因此您应该考虑将其包装在 using 语句中(或使用新的 C# 8 using 声明)。 - Marie