Während yield
ich verstand, wie ein Schlüsselwort funktioniert, bin ich bei StackOverflow auf Link1 und Link2 gestoßen, die die Verwendung von befürworten, yield return
während sie über den DataReader iterieren, und die auch meinen Anforderungen entsprechen. Aber ich frage mich, was passiert, wenn ich yield return
wie unten gezeigt verwende und nicht durch den gesamten DataReader iteriere. Bleibt die DB-Verbindung für immer offen?
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;
}
}
Ich habe das gleiche Beispiel in einer Beispiel-Konsolen-App ausprobiert und beim Debuggen festgestellt, dass der finally-Block von GetRecords()
nicht ausgeführt wird. Wie kann ich dann die Schließung der DB-Verbindung sicherstellen? Gibt es einen besseren Weg als das Verwenden von yield
Schlüsselwörtern? Ich versuche, eine benutzerdefinierte Klasse zu entwerfen, die für die Ausführung ausgewählter SQL-Anweisungen und gespeicherter Prozeduren in der Datenbank verantwortlich ist und das Ergebnis zurückgibt. Ich möchte den DataReader aber nicht an den Aufrufer zurückgeben. Außerdem möchte ich sicherstellen, dass die Verbindung in allen Szenarien geschlossen wird.
Bearbeiten Die Antwort auf Bens Antwort wurde geändert, da nicht erwartet werden kann, dass Methodenaufrufer die Methode korrekt verwenden. In Bezug auf die DB-Verbindung ist es teurer, wenn die Methode ohne Grund mehrmals aufgerufen wird.
Danke Jakob und Ben für die ausführliche Erklärung.