[VB.NET] Recursieve Functie {Part 2}

Pagina: 1
Acties:

  • MikevanEngelen
  • Registratie: Mei 2001
  • Laatst online: 15-05 12:18
Vanwege een eerder gesloten topic (http://gathering.tweakers.net/forum/list_messages/992084) nogmaals een poging.

De applicatie bestaat uit 2 delen, de database en het client gedeelte.
De database wordt aangesproken om een menu op te bouwen in de applicatie. Het menu bouwt zich op doormiddel van een kolom welke het vorige menu item opgeeft. En dit geeft als voordeel dat je onbeperkt diep kan gaan, met een redelijk overzichtelijk geheel.
Het probleem is echter wanneer ik een hoofditem/rootitem ga verwijderen, laat hij (logischer wijs) de rest van de items staan, dit houd in dat
1)de database 'volloopt' (en daardoor onoverzichtelijk(er) word)
2)wanneer ik een nieuw hoofd/root item aanmaak hij alle 'oude items' weer heeft onder het nieuwe hoofditem.
Wat er dus moet gebeuren is dat er dus een functie is/komt die er voor zorgt dat ook die subnodes/subitems worden verwijderd. Hier heb ik al wel naar gekeken, en ook een stukje code voor geschreven.
Ik zie zelf alleen niet echt waar het probleem zit.

Ik heb de code door de debugger gehaald en ' #1 tot ' 1# gaat perfect. Alleen wanneer ik de functie opnieuw aanspreek, loopt de boel de soep in.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
' #1
Sub subRecursief(ByVal intMenunr As Integer)
Dim dbCount As Integer

' leeghalen van de dataset (om 'rare' dingen te voorkomen)
 ds.Clear()

' functie om de database gegevens uit te laden, en 
' hier de records uit te halen welke ik later moet verwijderen.
' intMenunr is het "subitem" in dit geval, en die wordt dus ook meegegeven in deze 
' query om later het "menunummer" uit de query te krijgen.
 dbQuery(intMenunr)
 dbCount = ds.Tables("table1").Rows.Count - 1

' als er geen subitems zijn in de dataset, returned hij -1 hij moet wel het item 
' toevoegen omdat hij anders het hoofditem in het vervolg stuk niet kan verwijderen.
 If dbCount = -1 Then
  arrList.Add(intMenunr)
 Else

' stukje wat gegevens uit de dataset haalt, om daarna deze in de ArrayList
' (collection) te plaatsen om daarna de recursieve functie te starten welke dit 
' herhaaldelijk blijft doen.
Dim dbrecord As Data.DataRow
Dim i As Integer
 For i = 0 To dbCount
  Try
   dbrecord = ds.Tables("table1").Rows.Item(i)
   intMenunr = CInt(dbrecord("menunummer"))
   Try
    arrList.Add(intMenunr)
   Catch ex As Exception
    System.Diagnostics.Debug.WriteLine(ex.Message)
   End Try

'1#
   subRecursief(intMenunr)
  Catch ex As Exception
   System.Diagnostics.Debug.WriteLine(ex.Message)
  End Try
 Next i
End If
End Sub

Ik heb commentaar er nu bijgezet, in de hoop dat dit nu duidelijk genoeg is.
In principe gaat het eerste gedeelte dus goed, alleen wanneer hij die recursieve functie aanspreekt blijft hij loopen.

Dus mijn voornaamste vraag, zet ik die recursieve link (naar de procedure) op/naar de verkeerde plek, of maak ik programmeer-technisch een grote fout ? Het nadeel is dat je na een 1.5 uur kijken naar de zelfde code je uiteindelijk zelf ook door de bomen het bos niet meer ziet.

Ik hoop dat jullie me in dit geval wel kunnen helpen, en dat dit topic nu niet wordt gesloten.
Het mag dan wel een lang topic zijn, maar ik geef nu toch veel informatie. Heb tevens de 'onnozele' code weggehaald (volgens jou) maar anders kan ik me Watches niet in de gaten houden (dat laaste stukje code, had ik een breakpoint op).

  • Sjaaky
  • Registratie: Oktober 2000
  • Laatst online: 22-04 07:04
Ik heb niet heel goed naar je code gekeken, maar waarschijnlijk werkt het niet omdat je dataset niet lokaal is in de functie. Kortom je voert een query uit en krijgt resultaten, voor elk resultaat wil je subRecursief uitvoeren. En wat is het eerste dat deze doet? Hij gooit de dataset leeg waarover de aanroepende functie aan het lopen was.

  • pjotrk
  • Registratie: Mei 2004
  • Laatst online: 15-07-2025
probleem ligt volgens mij aan het feit dat de dataset globaal gedeclareerd is, en tijdens de recursie telkens weer wordt overschreven:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
' #1
Sub subRecursief(ByVal intMenunr As Integer)
  Dim dbCount As Integer

  ' leeghalen van de dataset (om 'rare' dingen te voorkomen)
  '= hier gaat het geloof ik fout omdat de resultaten van de vorige recursie nu ook weg zijn
  ds.Clear()


  ' functie om de database gegevens uit te laden, en 
  ' hier de records uit te halen welke ik later moet verwijderen.
  ' intMenunr is het "subitem" in dit geval, en die wordt dus ook meegegeven in deze 
  ' query om later het "menunummer" uit de query te krijgen.

  '= vult de dataset?
  dbQuery(intMenunr)


  '= niet zo net om er hier al 1 af te halen variable dient nu niet voor wat de naam doet vermoeden
  '^ dbCount = ds.Tables("table1").Rows.Count - 1
  dbCount = ds.Tables("table1").Rows.Count

  '^ If dbCount = -1 Then
  If dbCount = 0 Then
    arrList.Add(intMenunr)
  Else

   ' stukje wat gegevens uit de dataset haalt, om daarna deze in de ArrayList
   ' (collection) te plaatsen om daarna de recursieve functie te starten welke dit 
   ' herhaaldelijk blijft doen.

    Dim dbrecord As Data.DataRow
    Dim i As Integer
    '^ For i = 0 To dbCount
    For i = 0 To dbCount - 1
      Try
        dbrecord = ds.Tables("table1").Rows.Item(i)
        intMenunr = CInt(dbrecord("menunummer"))
        Try
          arrList.Add(intMenunr)
        Catch ex As Exception
          System.Diagnostics.Debug.WriteLine(ex.Message)
        End Try
'1#
        subRecursief(intMenunr)
    '= dataset is nu dus leeg (recursie gaat door totdat er een keer geen subnodes meer zijn)

      Catch ex As Exception
        System.Diagnostics.Debug.WriteLine(ex.Message)
      End Try
    Next i
  End If
End Sub


bovendien is het altijd het beste om verborgen 'features' van een functie (vullen en legen van een globale dataset) te voorkomen :)
niemand verwacht zomaar dat je tijdens de delete functie de globale dataset leegt en vult, globale variables kunnen daarom sowieso dus beter niet worden gebruikt

edit:
beetje te laat :X

[ Voor 6% gewijzigd door pjotrk op 28-12-2004 23:56 ]


  • MikevanEngelen
  • Registratie: Mei 2001
  • Laatst online: 15-05 12:18
pjotrk schreef op dinsdag 28 december 2004 @ 23:54:
probleem ligt volgens mij aan het feit dat de dataset globaal gedeclareerd is, en tijdens de recursie telkens weer wordt overschreven:

code:
1
2
3
4
5
6
7
8
' #1
Sub subRecursief(ByVal intMenunr As Integer)
  Dim dbCount As Integer

  ' leeghalen van de dataset (om 'rare' dingen te voorkomen)
  '= hier gaat het geloof ik fout omdat de resultaten van de vorige recursie nu ook weg zijn
  ds.Clear()
*knip*


bovendien is het altijd het beste om verborgen 'features' van een functie (vullen en legen van een globale dataset) te voorkomen :)
niemand verwacht zomaar dat je tijdens de delete functie de globale dataset leegt en vult, globale variables kunnen daarom sowieso dus beter niet worden gebruikt

edit:
beetje te laat :X
Hmm, op zich klopt het wel wat jullie zeggen, maar die waardes die ik nodig heb voor het verwijderen in het volgende stadium plaatst hij in een ArrayList (Collection). Vandaar dat naar mijn idee de dataset iedere keer leeg moet, om em daarna wil te kunnen vullen met gegevens...

  • pjotrk
  • Registratie: Mei 2004
  • Laatst online: 15-07-2025
Daarmee bedoel je dit stukje?

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  * knip *
    For i = 0 To dbCount - 1
      Try
        dbrecord = ds.Tables("table1").Rows.Item(i)
        intMenunr = CInt(dbrecord("menunummer"))
        Try
          arrList.Add(intMenunr)
        Catch ex As Exception
          System.Diagnostics.Debug.WriteLine(ex.Message)
        End Try
'1#
        subRecursief(intMenunr)
    '= dataset is nu dus leeg (recursie gaat door totdat er een keer geen subnodes meer zijn)

      Catch ex As Exception
        System.Diagnostics.Debug.WriteLine(ex.Message)
      End Try
    Next i
  * knip *


Daar gaat het juist fout geloof ik, de eerste for loop gaat nu goed, maar de 2e keer dat hij dat for lusje passeert (dus wanneer i = 1) is de dataset geloof ik leeg.

  • MikevanEngelen
  • Registratie: Mei 2001
  • Laatst online: 15-05 12:18
Nu je dit zo zegt, klopt dit inderdaad wel.

Maar heb je enig idee hoe ik dat anders zou kunnen oplossen. Aangezien hij de boel moet legen vanwege een record aantal van 1xx :S

  • MrSleeves
  • Registratie: Februari 2004
  • Laatst online: 10-04 19:23

MrSleeves

You'll thank me later.

MikevanEngelen schreef op woensdag 29 december 2004 @ 09:04:
Nu je dit zo zegt, klopt dit inderdaad wel.

Maar heb je enig idee hoe ik dat anders zou kunnen oplossen. Aangezien hij de boel moet legen vanwege een record aantal van 1xx :S
Allereerst geef je de dataset steeds door als variabele in de subroutine:
Visual Basic .NET:
1
Public Sub subRecursief(ByVal intMenunr As Integer, ByVal deSet as Dataset)


Maar misschien is er ook een makkelijkere oplossing: In bv TreeNodes wordt de node met "\" gesplitst. Dat zou je ook kunnen doen, dus zoiets als
"Bestand\"
"Bestand\Open\"
"Bestand\Nieuw\"
"Bestand\Bla\Bla\" (altijd een "\" aan het eind i.v.m. naam die begint met "Bestand..."

Als je Node "Bestand" gaat wissen, hoef je alleen een query los te laten met een delete waar de naam begint met "Bestand"+"\".

Is maar een ideetje...
Heeft er ook mee te maken dat je met recursie veel resources opvreet. Dat vind ik bijna nooit erg, maar als je databases gaat benaderen in je sub wel. Je moet eigenlijk één keer een query doen en dan een recursieve functie. En dus geen query in de recursieve functie.

[ Voor 5% gewijzigd door MrSleeves op 29-12-2004 10:06 ]

30Drie Web Design & IT Consultancy | Raven Consultancy Services


  • MikevanEngelen
  • Registratie: Mei 2001
  • Laatst online: 15-05 12:18
Allen dank, heb het met de volgende code opgelost:


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    Sub subRecursief(ByVal intMenunr As Integer)
        Dim dbCount As Integer
        Dim ds As New Data.DataSet

        If Not dbOpen() Then
            MsgBox("Databeest error")
            dbClose()
        Else
            da.SelectCommand = New ByteFX.Data.MySqlClient.MySqlCommand
("SELECT * FROM TBL_SITECONTENT_MENU WHERE SUBMENU='" & intMenunr & "'", dbcon)
            da.Fill(ds, "table1")
            dbClose()
        End If
        dbClose()
        dbCount = ds.Tables("table1").Rows.Count

        Dim dbrecord As Data.DataRow
            Dim i As Integer
            For i = 0 To dbCount - 1
                Try
                    dbrecord = ds.Tables("table1").Rows.Item(i)
                    intMenunr = CInt(dbrecord("menunummer"))
                    arrList.Add(intMenunr)
                    subRecursief(intMenunr)
                Catch ex As Exception
                    System.Diagnostics.Debug.WriteLine(ex.Message)
                End Try
        Next i
    End Sub

[ Voor 6% gewijzigd door MikevanEngelen op 29-12-2004 10:08 ]


  • MrSleeves
  • Registratie: Februari 2004
  • Laatst online: 10-04 19:23

MrSleeves

You'll thank me later.

MikevanEngelen schreef op woensdag 29 december 2004 @ 10:08:
Allen dank, heb het met de volgende code opgelost:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    Sub subRecursief(ByVal intMenunr As Integer)
        Dim dbCount As Integer
        Dim ds As New Data.DataSet

        If Not dbOpen() Then
            MsgBox("Databeest error")
            dbClose()
        Else
            da.SelectCommand = New ByteFX.Data.MySqlClient.MySqlCommand
("SELECT * FROM TBL_SITECONTENT_MENU WHERE SUBMENU='" & intMenunr & "'", dbcon)
            da.Fill(ds, "table1")
            dbClose()
        End If
        dbClose()
        dbCount = ds.Tables("table1").Rows.Count

        Dim dbrecord As Data.DataRow
            Dim i As Integer
            For i = 0 To dbCount - 1
                Try
                    dbrecord = ds.Tables("table1").Rows.Item(i)
                    intMenunr = CInt(dbrecord("menunummer"))
                    arrList.Add(intMenunr)
                    subRecursief(intMenunr)
                Catch ex As Exception
                    System.Diagnostics.Debug.WriteLine(ex.Message)
                End Try
        Next i
    End Sub
Als details: Het is mooier/beter om die Arraylist arrList als ByRef mee te geven aan de subroutine.

30Drie Web Design & IT Consultancy | Raven Consultancy Services

Pagina: 1