在了解yield
关键字的工作原理的同时,我遇到了StackOverflow 上的link1和link2,它主张yield return
在DataReader 上进行迭代时使用它,它也适合我的需求。但是,这使我感到奇怪,如果发生如下情况,如果我yield return
按如下所示使用,并且如果我不遍历整个DataReader,那么数据库连接会永远保持打开状态吗?
IEnumerable<IDataRecord> GetRecords()
{
SqlConnection myConnection = new SqlConnection(@"...");
SqlCommand myCommand = new SqlCommand(@"...", myConnection);
myCommand.CommandType = System.Data.CommandType.Text;
myConnection.Open();
myReader = myCommand.ExecuteReader(CommandBehavior.CloseConnection);
try
{
while (myReader.Read())
{
yield return myReader;
}
}
finally
{
myReader.Close();
}
}
void AnotherMethod()
{
foreach(var rec in GetRecords())
{
i++;
System.Console.WriteLine(rec.GetString(1));
if (i == 5)
break;
}
}
我在示例控制台应用程序中尝试了相同的示例,并在调试时注意到GetRecords()
未执行的finally块。我怎样才能确保关闭数据库连接?有没有比使用yield
关键字更好的方法?我正在尝试设计一个自定义类,该类将负责在数据库上执行选择的SQL和存储过程,并将返回结果。但是我不想将DataReader返回给调用者。我还要确保在所有情况下都将关闭连接。
编辑将答案更改为Ben的答案,因为期望方法调用者正确使用该方法是不正确的,并且对于DB连接,如果无缘无故多次调用该方法,则将更加昂贵。
感谢Jakob和Ben提供详细说明。