Was ist/bedeutet SqlConnection.Open
- VB.NET
- .NET (FX) 4.5–4.8
Sie verwenden einen veralteten Browser (%browser%) mit Sicherheitsschwachstellen und können nicht alle Funktionen dieser Webseite nutzen.
Hier erfahren Sie, wie einfach Sie Ihren Browser aktualisieren können.
Hier erfahren Sie, wie einfach Sie Ihren Browser aktualisieren können.
Es gibt 32 Antworten in diesem Thema. Der letzte Beitrag () ist von Haudruferzappeltnoch.
-
-
Mein Nichtinformatikerverständnis wiedergebend:
Das Verhalten von Werte- und Referenztypen beiByVal
undByRef
ist etwas schwer zu erfassen.
ByRef
führt dazu, dass derselbe Speicherplatzinhalt verwendet wird. Diuretisches Beispiel:
VB.NET-Quellcode
- Private Sub Foo()
- Dim X As Integer = 5
- NennMirDieAdresseAnDerFolgendeVariableGepeichertIst(X) 'Ergebnis &H0815ABBA
- SubMitByVal(X)
- SubMitByRef(X)
- End Sub
- Private Sub SubMitByVal(Variable As Integer)
- NennMirDieAdresseAnDerFolgendeVariableGepeichertIst(Variable) 'Ergebnis &H423A5EE
- End Sub
- Private Sub SubMitByRef(ByRef Variable As Integer)
- NennMirDieAdresseAnDerFolgendeVariableGepeichertIst(Variable) 'Ergebnis &H0815ABBA
- End Sub
Bei Wertetypen:
BeiByRef
wird die Speicheradresse an die Sub übermittelt und so derselbe Speicherinhalt innerhalb der Sub verwendet. Demenstprechend wird der Inhalt der übergebenden Variable in/ausFoo
verändert, wenn man die Variable in der Sub ändert.
BeiSubMitByVal
wird stattdessen der Wert der Variablen übergeben, also eine neue Variable angelegt und mit dem gleichen Wert versehen wie die Originalvariable. Es gibt jetzt also 2 Variablen mit dem gleichen Wert im Speicher. Ändert man jetzt den Wert der einen, ist das der anderen egal.
Nun aber Refenztypen:
Da werden unabhängig davon, ob manByVal
oderByRef
übergibt, nicht die Objekte an sich (weil die sehr groß sein können), sondern intern deren Speicheradressen übergeben. Und damit arbeitet die aufgerufene Sub weiter. Also wird in der Sub somit immer automatisch auf das Originalobjekt zugegriffen. Eben weil keine Kopie angelegt wird wie bei Wertetyp+ByVal. Dadurch scheint es erstmal egal zu sein, ob man eine Referenztypobjektinstanz perByVal
oder perByRef
übergibt. Aber es gibt ein paar Fälle, in denen man auch solch ein Objekt perByRef
übergeben muss.
Und jetzt eben noch:
Wird ein Referenztypinstanz wie ne SqlConnection (da der Typ eine Klasse ist) in einer Sub erstellt, wird diese solange am Leben erhalten, wie sie gebraucht wird. Wird die Instanz an eine aufrufende Methode zurückgegeben, wird dem GarbageCollector klargemacht, dass das Teil wohl noch weiterverwendet wird und nicht vernichtet werden darf. Erst wenn es keine gültige Variable mehr gibt, die auf diese SqlConnection verweist, wird sie zum Abschuss freigegeben.
DeineByRef
-Übergabe (oder ebenByval
-Übergabe) der SqlConnection an eine Sub und die dortigeDispose
ierung ist aber dem obigen Verhalten geschuldet: Das Originalobjekt wird hier plattgemacht, weil man dieses hier an der Angel hat. Es wird bei Subaufruf keine Kopie erstellt.
In Summe: Zwei Verhaltensweisen, die verhaltenstechnisch ähnlich aussehen, aber andere Gründe haben.
Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.
Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln. -
Danke für die Erklärung, finde ich gut nachvollziehbar. Der Punkt mit dem Speicherplatz ist denke ich der Relevanteste. Ich dachte nämlich ByVal, ByRef und FunctionReturnte Variable kriegen alle einen eigenen Speicherplatz. Aber jetzt ist auch klar, das erscheint natürlich eine riesen Verschwendung. So tief konnte ich noch nicht schauen.
-
Ich sag nur immer wieder: Lies ein Buch.
Du hast hier zwei ganz wichtige Grundlagen-Themen berührt:- ByVal/ByRef - Parameter-Übergabe
- Referenz-/Wert-Datentypen
Und zwar das zweite zuerst, denn sowohl Referenz- als auch Wert-Datentypen werden als Parameter an Methoden übergeben (und zwar jeweils mal ByVal, mal ByRef).
Es geht auch an keiner Stelle um Verschwendung von Speicherplatz.
Es geht darum, ob man mit "Zeigern" (Referenzen) auf Speicherplatz arbeitet oder mit Speicherplatz-Kopien.
Beides ist je nach Umständen das angemessenere.
Gibts da eiglich nix im Allgemein-Tutorial-Bereich?
- ByVal/ByRef - Parameter-Übergabe
-
-
@Haudruferzappeltnoch Verständlicher wird es vielleicht, wenn Du ein Array oder eine List(Of T) mit ByRef oder ByVal übergibst.
Überlege zuerst, was da passiert, bevor Du den Code ausführst:
VB.NET-Quellcode
- Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
- Dim ll = New List(Of Integer) From {1, 2, 3, 4, 5}
- DoIt1(ll)
- MessageBox.Show(ll.ToString())
- DoIt2(ll)
- MessageBox.Show(ll.ToString())
- End Sub
- Sub DoIt1(ByVal li As List(Of Integer))
- li = Nothing
- End Sub
- Sub DoIt2(ByRef li As List(Of Integer))
- li = Nothing
- End Sub
Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch
Ein guter .NET-Snippetkonverter (der ist verfügbar).
Programmierfragen über PN / Konversation werden ignoriert! -
Ja das Verhalten, was dieser Code zeigt, war mir schon lange bewusst. MessageBox Nr 2 hat keinen String mehr drin und es gibt ne Exception, ich denke mal weil
Nothing
keine.ToString
Methode hat
Aber das gibt ja keinen Rückschluss auf die verwendeten Speicherplätze. Wir haben es ja bereits klären können, bei ByVal zwei (nichtmal das immer) bei ByRef einer.
Danke euch
Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()
-
Haudruferzappeltnoch schrieb:
weilNothing
keine.ToString
Methode hat
Die Methode heißt: "Lernen durch Schmerz". Eine exception hat, denke ich, einen größeren Lerneffekt als eine Ausgabe in einem Label.Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch
Ein guter .NET-Snippetkonverter (der ist verfügbar).
Programmierfragen über PN / Konversation werden ignoriert! -
Ich hab hier mal ein Beispiel, wo ich einen DataAdapter aus einer anderen Klasse bekomme, wie
Dispose
ich dort denn jetzt im Nachhinein die Connection wieder?
Weil sie lokal definiert ist, kann ich die ja nicht ansprechen. Ich dachte vielleicht muss ich noch eine Dispose Sub in der DBZugriff Klasse basteln, aber dann hab ich immer noch die Connection lokal, also müsste ich die auf Klassenebene definieren?
VB.NET-Quellcode
- Public Class Form1
- Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
- Dim DBZ As New DBZugriff("sql")
- DBZ.DB1Adapter.Fill(DS1.dt1)
- End Sub
- End Class
- Friend Class DBZugriff
- Private SqlString As String
- Friend Sub New(sql As String)
- SqlString = sql
- End Sub
- Friend Function DB1Adapter() As SqlDataAdapter
- Dim cn As New SqlConnection("bla")
- Dim da As New SqlDataAdapter(SqlString, cn)
- Return da
- End Function
- End Class
-
Korrekt. Du könntest zwar der
DBZugriff
-Klasse das Disposen beibringen, indem Du dasIDisposable
-Interface implementierst. Dann kannst Du zwar lokal einenUsing
-Block nutzen (also in Deinem Beispiel inForm1_Load
) und wenn Du das vergisst, könnte Dich ggf. VS darauf hinweisen, dass da einUsing
/Dispose
fehlt. Aber wenn Du es klassenweit machst, musst Du das Objekt entweder im Form-Disposing-Teil disposen oder Dich imFormClosing
-EventHandler drum kümmern. Aber drum kümmern musst Du Dich immer selbst.
Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.
Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln. -
Sry da komm ich nicht hinterher, mit Objekt meinst du jetzt die Instanz DBZ?
Wenn ich Using im .Load nutze, dann könnte ich das höchstens mit DBZ selbst tun oder? Das erwischt dann auch die Connectioncn
?
Wie kann ich denn sehen dass etwas richtig disposed ist?
Das Closing-Event ist nicht gut genug. Das wird in nem Programm laufen, das sehr lange in Betrieb ist. Ich denke die Verbindung sollte nach ihrem Nutzen Disposed werden.
Die IDisposable Schnittstelle liefert sowas:
Spoiler anzeigen VB.NET-Quellcode
- Private disposedValue As Boolean ' Dient zur Erkennung redundanter Aufrufe.
- ' IDisposable
- Protected Overridable Sub Dispose(disposing As Boolean)
- If Not disposedValue Then
- If disposing Then
- ' TODO: verwalteten Zustand (verwaltete Objekte) entsorgen.
- End If
- ' TODO: nicht verwaltete Ressourcen (nicht verwaltete Objekte) freigeben und Finalize() weiter unten überschreiben.
- ' TODO: große Felder auf Null setzen.
- End If
- disposedValue = True
- End Sub
- ' TODO: Finalize() nur überschreiben, wenn Dispose(disposing As Boolean) weiter oben Code zur Bereinigung nicht verwalteter Ressourcen enthält.
- 'Protected Overrides Sub Finalize()
- ' ' Ändern Sie diesen Code nicht. Fügen Sie Bereinigungscode in Dispose(disposing As Boolean) weiter oben ein.
- ' Dispose(False)
- ' MyBase.Finalize()
- 'End Sub
- ' Dieser Code wird von Visual Basic hinzugefügt, um das Dispose-Muster richtig zu implementieren.
- Public Sub Dispose() Implements IDisposable.Dispose
- ' Ändern Sie diesen Code nicht. Fügen Sie Bereinigungscode in Dispose(disposing As Boolean) weiter oben ein.
- Dispose(True)
- ' TODO: Auskommentierung der folgenden Zeile aufheben, wenn Finalize() oben überschrieben wird.
- ' GC.SuppressFinalize(Me)
- End Sub
Das wird ja kompliziert
Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()
-
Haudruferzappeltnoch schrieb:
mit Objekt meinst du jetzt die Instanz DBZ?
Haudruferzappeltnoch schrieb:
Wenn ich Using im .Load nutze, dann könnte ich das höchstens mit DBZ selbst tun oder? Das erwischt dann auch die Connection cn?
Haudruferzappeltnoch schrieb:
Wie kann ich denn sehen dass etwas richtig disposed ist?
Haudruferzappeltnoch schrieb:
Ich denke die Verbindung sollte nach ihrem Nutzen Disposed werdenUsing
-Block oder, wenn Du das Objekt länger brauchst, durch explizites disposen, alsoDBZ.Dispose
aufrufen.
Haudruferzappeltnoch schrieb:
Das wird ja kompliziert
Nee, kopliziert sieht es nur aus. Wenn Du alle Kommentare entfernst, kannst Du das zusammendampfen:
VB.NET-Quellcode
- Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
- Using DBZ As New DBZugriff("sql")
- DBZ.DB1Adapter.Fill(DS1.dt1)
- End Using
- End Sub
- End Class
- Friend Class DBZugriff : Implements IDisposable
- Private SqlString As String
- Private disposedValue As Boolean
- Private cn As New SqlConnection("bla")
- Private da As New SqlDataAdapter(SqlString, cn)
- Friend Sub New(sql As String)
- SqlString = sql
- End Sub
- Friend Function DB1Adapter() As SqlDataAdapter
- Dim cn As New SqlConnection("bla")
- Dim da As New SqlDataAdapter(SqlString, cn)
- Return da
- End Function
- Protected Overridable Sub Dispose(disposing As Boolean)
- If disposedValue Then Return
- If disposing Then
- cn.Dispose() : cn = Nothing
- da.Dispose() : da = Nothing
- End If
- disposedValue = True
- End Sub
- Public Sub Dispose() Implements IDisposable.Dispose
- Dispose(True)
- GC.SuppressFinalize(Me)
- End Sub
- End Class
Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.
Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln. -
Danke dir @VaporiZed. Ich hab etwas ganz ähnliches gebastelt. Dann bin ich ja schonmal froh, dass das kein Humbug war. Ganz verstehen tu ich diese Schnittstelle noch nicht, aber das habe ich in einen anderen Thread ausgelagert.
-
Ähnliche Themen
-
vbn00b - - Daten(bank)programmierung
-
johnnyderdepp - - Daten(bank)programmierung
-
9 Benutzer haben hier geschrieben
- Haudruferzappeltnoch (15)
- VaporiZed (5)
- VB1963 (3)
- ErfinderDesRades (3)
- RodFromGermany (2)
- ISliceUrPanties (2)
- rrobbyy (1)
- mrMo (1)
- Montoyafan (1)