Meine Methode, die SQL Server aufruft, gibt eine DataReader
zurück, aber aufgrund dessen, was ich tun muss - was die DataReader
an die aufrufende Methode zurückgibt, die sich in einer Seitenkennung befindet - kann ich die Verbindung nicht schließen in der Klasse der Methode, die SQL Server aufruft. Aus diesem Grund habe ich keine oder blockweise.
Ist die richtige Art Ressourcen zu verteilen, damit die Klasse IDisposable
implementiert? Alternativ sollte ich die nicht verwaltete Ressource (Felder auf Klassenebene) vom Aufrufer explizit disponieren?
EDIT: Ich sende den Datenreader zurück, weil ich bestimmte Daten vom Datenreader an ein Listenelement-Steuerelement binden muss, also in der aufrufenden Klasse (Codebehind-Seite) mache ich:
%Vor% Ich würde ja sagen, implementieren Sie IDisposable
. Einer der Hauptgründe, soweit ich es sagen kann, ist, wenn man dem Benutzer des Objekts nicht genug vertrauen kann, um es selbst richtig zu machen. Dies scheint ein Hauptkandidat dafür zu sein.
Dies gesagt, aber es gibt eine Frage zu Ihrer Architektur. Warum möchten Sie das DataReader
selbst an die Seite senden, anstatt eine Methode aufzurufen, die es für Sie erledigt (einschließlich der relevanten Bereinigung), indem Sie das Notwendige zurücksenden? Wenn es notwendig ist, der Seite den eigentlichen Leser zu geben, dann sei es so.
Die Datenbankverbindung als Membervariable in Ihrer Reader-Klasse zu halten und Ihre Leserklasse dazu zu bringen, IDisposable zu implementieren, scheint mir in Ordnung zu sein.
Sie können jedoch in Betracht ziehen, dass Ihre Methode IEnumerable zurückgibt und yield return
-Anweisungen verwendet, um durch den Datenleser zu gehen. Auf diese Weise können Sie die Ergebnisse zurückgeben und trotzdem von Ihrer Methode bereinigen.
Hier ist eine grobe Skizze dessen, was ich meine:
%Vor%Ja, Sie sollten IDisposable für Ihre benutzerdefinierte Klasse implementieren, wenn sie einen DataReader enthält, der geöffnet ist, wenn er auf eine niedrigere Ebene zurückgegeben wird.
Es ist das akzeptierte Muster, wenn etwas zurückgegeben wird, das aufgeräumt werden muss.
Erstens ist die Übergabe von DataReader
möglicherweise nicht das, was Sie tun möchten, aber ich nehme an, dass es das ist.
Der richtige Weg, um dies zu handhaben, wäre, einen zusammengesetzten Typ zurückzugeben, der entweder DataReader
einkapselt oder verfügbar macht und an der Verbindung hält, und dann IDisposable
für diesen Typ zu implementieren. Wenn Sie diesen Typ entsorgen, entsorgen Sie sowohl den Reader als auch die Verbindung.
Die allgemeine Regel lautet, dass Ihre Klasse IDisposable
implementieren sollte, wenn sie direkt nicht verwaltete Ressourcen enthält oder einen Verweis auf ein anderes IDisposable
-Objekt enthält. Wenn Ihre Klasse in einer Methode IDataReader
erstellt, diese Referenz aber nie enthält, müsste Ihre Klasse nicht IDisposable
pro Regel implementieren (es sei denn, sie enthält einfach eine IDisposable
neben der IDataReader
, die in dieser Klasse erstellt wurde eine Methode).
Die wirkliche Frage, die Sie sich stellen müssen, ist, ob Ihre Klasse wirklich an diesem IDataReader
festhalten sollte, auch nachdem sie es an den Aufrufer geliefert hat. Persönlich halte ich das für ein schlechtes Design, weil es die Eigentumslinie verwischt. Wem gehört in diesem Fall tatsächlich die IDisposable
? Wer ist für seine Lebenszeit verantwortlich? Nimm zum Beispiel die Klasse IDbCommand
. Sie erstellen IDataReader
Instanzen und geben sie an die Aufrufer zurück, aber geben sich selbst frei. Das macht die API sauber und die Verantwortung für die Lebensdauerverwaltung ist in diesem Fall eindeutig.
Unabhängig von der Eigentumsfrage erfordert Ihre spezifische Situation die Implementierung von IDisposable; Nicht, weil Ihre Klasse zufälligerweise eine IDataReader
-Instanz erstellt und zurückgibt, sondern weil sie sich anhört, als ob sie ein IDbConnection
-Objekt enthält.
Tags und Links .net c# idisposable sqldatareader