Announcement

Collapse
No announcement yet.

Variablenwert erhalten

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Variablenwert erhalten

    Ich habe eine Klasse in der zwei Functions sind. In der ersten Function wird ein Wert in eine Variable gespeichert (es ist aber nicht das Ergebnis der Function, wird also nicht durch ein Return freigesetzt), den ich in der zweiten Function wieder brauche.
    Jedoch wird der Wert der Variable zurückgesetzt, sobald die erste Function abgearbeitet wurde. Der Datentyp der Variable ist Int und der Wert wird durch SQL ermittelt (ID einer Tabelle). In Function 2 brauch ich die ID dann um mit where zu vergleichen.
    Beim Debuggen ist angegeben, dass in der Variable 10 steht, solange die erste Function abgearbeitet wird (und so soll es für den Datensatz den er momentan liest auch sein). Das Speichern ist also nicht das Problem.

    Die Variable war zuerst über Property deklariert, darüber hab ich aber gelesen, dass diese nach jeder Verwendung zurückgesetzt werden.
    Das ganze global zu deklarieren hat leider auch nicht funktioniert. Auch hier wurde der Wert auf 0 zurückgesetzt.

    Gib es eine Möglichkeit, wie ich den Wert der Variable erhalten kann, bis sie mit einem neuen Wert gefüllt wird?

  • #2
    Hallo,

    das entscheidende Stichwort ist "Gültigkeitsbereich der Variablen", was dir - siehe den Hinweis auf "global" - vermutlich klar ist. Du musst also den bisherigen Wert "irgendwo" zwischenspeichern, wo die zweite Funktion darauf Zugriff hat. Das kann "global" innerhalb der Klasse sein, die die beiden Funktionen enthält, oder auch nur "global" innerhalb der Klasse, zu der die zweite Funktion gehört; die erste Funktion ändert diesen Wert durch einen anderen public-Zugriff.

    Aber mehr zu sagen, geht schon sehr stark in Richtung Spekulation. Nur wenn du mehr sagst über die Klassen und Methoden und diese Variable, sind konkrete Antworten möglich.

    Gruß Jürgen

    Comment


    • #3
      Die Variable war zuerst über Property deklariert, darüber hab ich aber gelesen, dass diese nach jeder Verwendung zurückgesetzt werden.
      Properties werden nicht vom System einfach so verändert da muss man schon selbst dran gedreht haben. Am besten du zeigst uns ein wenig Code dann verstehen wir wahrscheinlich besser was du meinst.

      Comment


      • #4
        Originally posted by Ralf Jansen View Post
        Properties werden nicht vom System einfach so verändert da muss man schon selbst dran gedreht haben. Am besten du zeigst uns ein wenig Code dann verstehen wir wahrscheinlich besser was du meinst.
        Also ich hab gelesen die werden automatisch zurückgesetzt dank einer DataReset Eigenschaft oder so was (schon ne Weile her...).

        Hier der Code (etwas gekürzt):

        [highlight=vbnet]
        Public Class SourceTable
        (Datenbank, Tabellenname... festsetzen)
        Dim test As Integer

        (Propertys und Functions...)



        Public Function funct1() As String()

        (Datenbankverbindung...)

        da = New OleDbDataAdapter("SELECT TOP 1 ID, Name1, Strasse, Hausnummer, PLZ, Ort FROM " & sTableName & " WHERE Bedingung1 is null and Bedingung2 is null;", conn)
        da.Fill(datset)

        test = datset.Tables(0).Rows(0).Item(0)

        (Daten in DataTable und Array schreiben)
        Return Ergebnis1
        End Function



        Public Function funct2() As String()

        (Datenbankverbindung...)

        da = New OleDbDataAdapter("SELECT TOP 1 CNr, C_Name1 & ' ' & C_Name2 & ' ' & C_Name3 as [C_Namen], C_Strasse, Crefo_Hausnummer," & _
        "C_PLZ, TestDaten.C_Ort FROM " & sTableName & " WHERE ID = " & test & ";", conn)
        da.Fill(datset)

        (Daten in DataTable und Array schreiben)
        Return Ergebnis2
        End Function
        [/highlight]

        Alles was Fehlerbehandlung angeht hab ich mal rausgelassen, ebenso wie die Schleifen, die die Stringarrays füllen.

        Ich habe es eben nochmal so getestet (habe auch für Dim am Anfang andere Befehle benutzt) aber test ist in der zweiten Function immernoch 0, obwohl in Funct1 angezeigt wird, dass test 10 wäre...

        Lass ich das mit der test-Variable raus, funktioniert alles einwandfrei, aber ich brauche sie nunmal, da ich die gelesenen Datensätze auch noch verändern muss.

        Vllt hilft euch das ja...

        Comment


        • #5
          Also wenn Du das wirklich so in Deinem Programm hast, dann MUSS das funktionieren. Natürlich unter der Voraussetzung, dass Du funct2 NACH funct1 aufrufst. Ausserdem darf test natürlich nicht verändert werden.
          Eventuall schaust Du Dir mal alle Codestellen an an denen auf test geschrieben wird. Oft übersieht man nur ganz banale Dinge.

          Comment


          • #6
            Hi Imari,

            Bist Du sicher, dass Du nicht zufälligerweise im Block (Datenbankverbindung...) selbst die Variable test nochmal definierst? In dem Fall würde die lokale Variable test die globale Variable test überblenden. Außerdem ist die Variable hier keine globale Variable sondern eine Instanzvariable, wird also nicht unter verschiedenen Objekten geteilt, der Wert wird also nur erhalten bleiben, wenn func1 und func2 entweder innerhalb der Klasse oder immer vom gleichen Objekt her aufgerufen werden.

            Ansonsten Grundlegendes für die Programmierung: nenne globale Variablen (oder wie hier Instanzvariablen) NIEMALS test, beispiel, dummy usw. Gerade Variablen, auf die aus mehreren Kontexten heraus zugegriffen werden muss (sonst wäre sie ja nicht global) sollten immer einen sprechenden Namen haben. Einerseits ermöglichst Du selbst den Überblick, wofür die Variable verwendet wird, und außerdem verhinderst Du damit Überblendungen durch lokale Variablen, die ja sehr gerne mal dummy heißen. Eine vernünftiges Klassendesign gibt Dir ja dann meist schon vor, wie die Variable verwendet wird (bzw. welche Information sie trägt), und das sollte sich im Variablennamen widerspiegeln.

            Comment


            • #7
              Dass man eine Variable nicht so nenen sollte, ist mir klar. Ich wollte sie umbenennen sobald alles geht...

              Funct1 wird definitiv vor Funct2 aufgerufen.
              Eine weitere Deklarierung der Variable (die jetzt IdTable heißt) gibt es nicht.
              Geändert wird sie auch nicht nachdem sie den Wert bekommt, den sie haben soll.
              Der Wert ist 0, sobald ich Funct2 aufrufe.

              Hat wer ne Idee woran es noch liegen könnte?
              Ich dachte erst, weil Funct1 möglicherweise nicht ganz durchläuft und darum Return Nothing als Ergebnis kommt. Aber einerseits läuft Funct1 ohne Fehler und das Return hat ja auch eigentlich nichts mit der Variable an sich zu tun...

              Woran könnte der Wert der Variable noch hängen?
              Gibt es irgedeneine andere Variable oder so (z.B. der Connectionstring), der noch im Nachhinein Einfluss auf den Wert haben kann? (Jetzt wirds unrealistsich, aber meine Verzweiflung nimmt stetig zu )

              Comment


              • #8
                Ach je, es geht ja um Oledb. Das ist bekannt für seltsame Fehler, wenn Variable bzw. ihre Inhalte per String-Verknüpfung in einen SQL-Befehl eingebaut werden. Benutze unbedingt Parameter, das könnte schon zum Ergebnis führen.

                Ausführliche Erläuterungen (in C#) siehe z.B. [Artikelserie] Parameter von SQL Befehlen.

                Gruß Jürgen

                Comment


                • #9
                  Rufst du vielleicht funct1 und funct2 nicht an der selben Instanz der SourceTable Klasse auf?

                  Wenn das Problem ist würde ich aus dem test Feld (wieder?) eine Property machen und mal mit einem Breakpoint im Setter der Property debuggen um rauszufinden von wo sich die ändert. (Das Feld hinter der Property natürlich dabei von nirgendwo direkt ansprechen)


                  Ich habe es eben nochmal so getestet (habe auch für Dim am Anfang andere Befehle benutzt) aber test ist in der zweiten Function immernoch 0, obwohl in Funct1 angezeigt wird, dass test 10 wäre...
                  Andere Möglichkeit, wo in funct2 hast du die 0 gesehen? Vor oder nach dem da.Fill(datset). Und wieso musst du nach dem Fill(dataset) die Daten noch in eine Datatable schreiben die sind dann doch schon in einer Datatable?

                  Comment


                  • #10
                    Originally posted by Ralf Jansen View Post
                    Andere Möglichkeit, wo in funct2 hast du die 0 gesehen? Vor oder nach dem da.Fill(datset).
                    Ich sehs, im SQL-Befehl. Wenn ich einen Breakpoint setze gibt er mir bei test = 0 an, obwohl der Wert ja eigentlich auf 10 festgesetzt sein müsste...
                    Im datset steht desshalb natürlich nix... es gibt je nichts zum Reinschreiben, da es keine Zeile mit der ID 0 gibt...

                    Comment


                    • #11
                      Originally posted by Jürgen Thomas View Post
                      Benutze unbedingt Parameter, das könnte schon zum Ergebnis führen.
                      Leider wird auch der Parameter auf 0 zurückgesetzt sobal Funct1 verlassen wird

                      Und nun bin ich inzwischen an einem Punkt an dem ich diese Problem auf die Reihe kriegen muss, da ich sonst nicht weiterarbeiten kann. *PC aus Fenster werf*

                      Comment


                      • #12
                        Dann solltest du den Aufruf der beiden Funktionen im Code nochmal zeigen vielleicht sehen wir dann was.

                        Comment


                        • #13
                          [highlight=vbnet]
                          Public Class SourceTable

                          Private oDataDescription As QualiDataSet
                          Private sConnectionString As String
                          Private datTable As DataTable
                          Private sTableName As String
                          Dim SqlPar As New SqlParameter("@Productname", SqlDbType.Int, 40)

                          (Properties...)

                          Public Function Funct1() As String()

                          Dim conn As OleDbConnection = New OleDbConnection(sConnectionString)
                          Dim datset As New DataSet
                          Dim da As OleDbDataAdapter
                          SaveFrstDataRcrdStr = Nothing

                          da = New OleDbDataAdapter("SELECT TOP 1 ID, Name1, Strasse, Hausnummer, PLZ, Ort FROM " & sTableName & " WHERE Bedingung1 is null and Bedingung2 is null;", conn)
                          da.Fill(datset)

                          SqlPar.Value = datset.Tables(0).Rows(0).Item(0)
                          datTable.Clear()
                          da.Fill(datTable)

                          Dim frstDataRcrd As String() = Nothing
                          For Each dr As DataRow In datTable.Rows()
                          For I As Integer = 0 To dr.ItemArray.Count - 1
                          ReDim Preserve frstDataRcrd(dr.ItemArray.Count - 1)
                          If IsDBNull(dr.ItemArray(I)) = True Then
                          frstDataRcrd(I) = Nothing
                          Else
                          frstDataRcrd(I) = dr.ItemArray(I).ToString
                          End If
                          Next
                          Next

                          conn.Close()
                          Return frstDataRcrd
                          End Function


                          Public Function Funct2() As String()

                          Dim conn As OleDbConnection = New OleDbConnection(sConnectionString)
                          Dim scndDatset As New DataSet
                          Dim da As OleDbDataAdapter
                          SaveScndDataRcrdStr = Nothing


                          da = New OleDbDataAdapter("SELECT TOP 1 CNr, C_Name1 & ' ' & C_Name2 & ' ' & C_Name3 as [C_Namen], C_Strasse, C_Hausnummer," & _
                          "C_PLZ, TestDaten.C_Ort FROM " & sTableName & " WHERE Id = " & SqlPar.Value & ";", conn)
                          da.Fill(scndDatset)

                          datTable.Clear()
                          da.Fill(datTable)

                          Dim scndDataRcrd As String() = Nothing

                          For Each dr As DataRow In datTable.Rows()
                          For I As Integer = 0 To dr.ItemArray.Count - 1
                          ReDim Preserve scndDataRcrd(dr.ItemArray.Count - 1)
                          If IsDBNull(dr.ItemArray(I)) = True Then
                          scndDataRcrd(I) = Nothing
                          Else
                          scndDataRcrd(I) = dr.ItemArray(I).ToString
                          End If
                          Next
                          Next

                          conn.Close()
                          Return scndDataRcrd
                          End Function
                          [/highlight]

                          Ihr habt es so gewollt
                          Habe nur die Abfragen nach Nothing und die Try-Befehle rausgelassen.

                          Comment


                          • #14
                            Ich meinte eigentlich den Code der Funct1 bzw.Funct2 aufruft und nicht deren Implementierung.

                            PS. Wie man SQLParameter benutzt solltest du nochmal in einem Buch nachschlagen. Oder den verlinkten Beitrag von Jürgen auch lesen und nicht nur überfliegen.

                            Comment


                            • #15
                              Die eigentliche Schwachstelle in Deinem Entwurf ist, dass Funct1 "heimlich" den Zustand von Variablen ändern soll. Wenn Funct2 einen Wert benötigt, sollte dieser Wert auch explizit übergeben werden (und am besten auch von Funct2 am Anfang auf Plausibiltät geprüft werden). Und wenn Funct1 den Wert ändert, gehört das auch explizit in die Schnittstelle der Funktion. Also in etwa so:

                              [highlight=vbnet]
                              [...] wie gehabt

                              Public Function Funct1(ByRef WertdergeaendertWird As Integer) As String()
                              [...]
                              End Function

                              Public Function Funct2(ByVal Wertderbenoetigtwird As Integer) As String()
                              [...]
                              End Function

                              Public Sub CallingSub()
                              [...]
                              Dim Wert As Integer = 0
                              Dim MyStringArray As String() = Funct1(Wert)
                              Dim MyStringArray2 As String() = Funct2(Wert)
                              [...]
                              End Sub

                              [/highlight]

                              Eine Kommunikation zwischen zwei Funktionen über globale Variablen sollte vermieden werden, wenn es nicht unbedingt notwendig ist, oder eine "Durchschleifung" der Information zu den benötigten Funktionen zu aufwendig ist. Globale Variablen und Instanzvariablen sollten immer einen Zustand/eine Eigenschaft dokumentieren, der/die sich durch Aufruf der Funktion auch ändert, und nicht nur zum Informationstranssport genutzt werden. Ausnahmen wie z.B. Initialisierungsdaten (ausder Registry oder einem INI-File) bestätigen die Regel...

                              Comment

                              Working...
                              X