【发布时间】:2010-10-22 16:16:26
【问题描述】:
背景:我有一堆从数据库中获取的字符串,我想返回它们。传统上,它会是这样的:
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一切都很好/灵活。所以我在想我可以使用“收益回报”类型的设计来处理这个......就像这样:
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();
}
}
}
}
但是现在我正在阅读更多关于产量的内容(在这样的网站上......msdn 似乎没有提到这一点),它显然是一个懒惰的评估器,它保持填充器的状态在预期中有人要求下一个值,然后只运行它直到它返回下一个值。
在大多数情况下这看起来不错,但使用 DB 调用,这听起来有点冒险。作为一个有点人为的例子,如果有人从我从数据库调用中填充的 IEnumerable 中请求一个 IEnumerable,通过它的一半,然后陷入循环......据我所知,我的数据库连接正在进行永远保持开放。
在某些情况下,如果迭代器没有完成,这听起来像是自找麻烦……我错过了什么吗?
【问题讨论】:
-
感谢您的编辑,乔恩...这就是我即时打字的结果。
-
只要您的消费者在 IEnumerator 上调用
Dispose,您就安全了。请参阅下面的帖子。 -
这有点不相关,我不确定当时是否属实,但对于未来的读者,
SqlDataReader实现了IDisposable所以你也应该将它包装在 using 语句中(或者一个新的 c# 8 using 声明)
标签: c# .net database resources yield