[VB.NET] Recursief Verwijderen

Pagina: 1
Acties:

  • MikevanEngelen
  • Registratie: Mei 2001
  • Laatst online: 01-05 19:11
...

Momenteel heb ik de volgende database indeling.
Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
Vader 
   \ Zoon
        \ Kind 1
        \ Kind 2
        \ Kind 3
   \ Dochter
        \ Kind 1
              \ Kind 1
        \ Kind 2
Moeder
    \ Zoon
    \ Dochter
[... etc ...]

Nu heb ik code geschreven die het voor mekaar krijgt dmv. een recursieve functie en daar krijg ik wel resultaten terug, maar niet de juiste.
Als ik Zoon verwijder van vader, haalt hij netjes kind 1 tot 3 weg. Echter als ik Vader weghaal haalt hij ook alleen zoon en de kinderen daaronder weg. Hij haalt dus niet de items die een niveau terug staan ook weg.
De items die hij moet verwijderen onthoud hij dmv. een ArrayList.

Ik bereik dit met de volgende code:
Visual Basic .NET:
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
54
55
56
57
58
59
60
61
62
63
64
65
66
Sub buttonclick handles buttonclick.click
        Dim intMenunummer As Integer
        Dim y As Integer
        Dim intAantal, intCount As Integer

        intMenunummer = modVariabelen.intSelectedItem

arrDelete.Clear()

            arrDelete.Add(intMenunummer)
            subRecursief(intMenunummer)
            intAantal = arrDelete.Count - 1

            For y = 0 To intAantal
                Dim dbRecord As Data.DataRow
                Dim intPaginanummer As Integer
                Dim intValue As Integer

                intValue = Nothing
                intPaginanummer = Nothing
                intMenunummer = Nothing
                intValue = arrDelete.Item(intCount)

[... dbcode voor verwijderen ...]

                If Not intAantal = intCount Then
                    intCount = intCount + 1
                End If
            Next y

        End If
End sub

Sub subRecursief(ByVal intMenunummer As Integer)
        Dim dbCount, dbAantal As Integer

        classBase.fVullenDataset("SELECT * FROM tbl_sitecontent_menu WHERE submenu='" & intMenunummer & "'", "tblRecursiefDelete", DS)
        classBase.fVullenDataset("SELECT count(*) AS dbCount FROM tbl_sitecontent_menu WHERE submenu='" & intMenunummer & "'", "tblRecursiefCount", DS)

        Dim dbRecordCount As Data.DataRow
        Try
            dbRecordCount = DS.Tables("tblRecursiefCount").Rows(0)
            dbAantal = dbRecordCount("dbCount").ToString
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try

        If Not dbAantal = 0 Then
            Dim dbRecord As Data.DataRow
            Dim i As Integer
            For i = 1 To dbAantal
                Try
                    dbRecord = DS.Tables("tblRecursiefDelete").Rows.Item(dbCount)
                    intMenunummer = CInt(dbRecord("menunummer"))
                    arrDelete.Add(intMenunummer)
                    '  subRecursief(intMenunummer)
                    If Not dbAantal = dbCount Then
                        dbCount = dbCount + 1
                    End If
                Catch ex As Exception
                    System.Diagnostics.Debug.WriteLine(ex.Message)
                End Try
            Next i
            subRecursief(intMenunummer)
        End If
End Sub


Heeft een van jullie een idee hoe ik dit op kan lossen. Ik weet dat ik hier eerder ook al om gevraagt heb, maar het idee is me gewoon niet duidelijk (genoeg) om er een werkelijke code oplossing van te maken. Kwa logische gedachten kom ik er wel bij, hij moet dus terug naar het niveau waar hij eerst was. Maar code matig heb ik geen idee hoe ik dat kan uitwereken.

Alvast heel erg bedankt, 't heeft me alweer een aantal uurtjes coden gekost met debuggen en word er nu beetje zat van ! Wat zie ik over het hoofd?

[ Voor 9% gewijzigd door MikevanEngelen op 27-06-2005 19:58 ]


  • mulder
  • Registratie: Augustus 2001
  • Laatst online: 12:34

mulder

ik spuug op het trottoir

pseudo
code:
1
2
3
4
5
6
7
8
Function RecDelete(id)
  If HasChildren(id) Then
    For Each Child In Children
      RecDelete(child.id)
    Next
  End If
  Delete(id)
End Function

oogjes open, snaveltjes dicht


  • sig69
  • Registratie: Mei 2002
  • Nu online
Kan je niet gewoon cascade delete aanzetten in je dbms?

Roomba E5 te koop


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 04-05 14:55

Janoz

Moderator Devschuur®

!litemod

Waarom staat er een ' voor de recursieve aanroep?

Waarom voer je die count query trouwens uit? Je kunt aan de resultset toch ook wel zien hoeveel items daarin zitten?

Na verder bestuderen klopt er eigenlijk geen ene hout van die queries in je recursiefe functie. Er wordt immers geen onderscheid gemaakt. Eerst vul je iets met alle records om vervolgens dat te overschrijven met de count.

[ Voor 40% gewijzigd door Janoz op 27-06-2005 16:27 ]

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • MikevanEngelen
  • Registratie: Mei 2001
  • Laatst online: 01-05 19:11
sig69 schreef op maandag 27 juni 2005 @ 16:24:
Kan je niet gewoon cascade delete aanzetten in je dbms?
Ik moet toegeven dat ik niet precies weet wat je bedoelt.
Echter het gaat hier om een MySQL database, waarmee je geen diagram relaties kan aanmaken, waardoor je dus automatisch een hele verzameling kan weggooien.

  • MikevanEngelen
  • Registratie: Mei 2001
  • Laatst online: 01-05 19:11
Janoz schreef op maandag 27 juni 2005 @ 16:25:
Waarom staat er een ' voor de recursieve aanroep?

Waarom voer je die count query trouwens uit? Je kunt aan de resultset toch ook wel zien hoeveel items daarin zitten?

Na verder bestuderen klopt er eigenlijk geen ene hout van die queries in je recursiefe functie. Er wordt immers geen onderscheid gemaakt. Eerst vul je iets met alle records om vervolgens dat te overschrijven met de count.
Die count query voer ik uit omdat ik mijn twijfels had aan de correctheid van de telling. Daarom dat ik de telling (voor de test) in de database laat plaatsvinden.
Die ' staat ervoor omdat ik een poosje getest heb wat het positiefste resultaat geeft.

In principe moet het gewoon dat alle items die in de database zitten die officieel verwijderd moeten worden ik opgeslagen wil hebben in een array. Dit omdat het gemakkelijk uit te lezen, en in de gaten te houden is. Tevens omdat ik gemakkelijk door de gegevens kan loopen en dan de items kan verwijderen.

  • MikevanEngelen
  • Registratie: Mei 2001
  • Laatst online: 01-05 19:11
Don Facundo schreef op maandag 27 juni 2005 @ 16:21:
pseudo
code:
1
2
3
4
5
6
7
8
Function RecDelete(id)
  If HasChildren(id) Then
    For Each Child In Children
      RecDelete(child.id)
    Next
  End If
  Delete(id)
End Function
Ik ga deze code morgen even proberen, in ieder geval bedankt.
(heb nu geen ontwikkelomgeving bij de hand)

  • MikevanEngelen
  • Registratie: Mei 2001
  • Laatst online: 01-05 19:11
MikevanEngelen schreef op maandag 27 juni 2005 @ 19:52:
[...]


Ik ga deze code morgen even proberen, in ieder geval bedankt.
(heb nu geen ontwikkelomgeving bij de hand)
Heb dit reeds geprobeerd, maar ook dit geeft niet het resultaat wat ik zou willen.
Hij loopt dan heeft hij bijvoorbeeld een volledige trap afgelopen, en dan returned hij naar het eerste item en doet ie vervolgens alles overnieuw. Maar eigelijk zou hij dit moeten doen, en dan controleren of er subitems zijn voor items die nog niet in de array staan...

Ik ben het stuur kwijt op deze boot ;)

Ik heb zijn code als volgt omgezet:
Visual Basic .NET:
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
    Function RecDelete(ByVal intID As Integer) As Boolean
        If Not Me.HasChildren(intID) = -1 Then
            RecDelete(intID)
        Else
            arrDelete.Add(intID)
        End If

    End Function

    Function HasChildren(ByVal intID As Integer) As Integer
        Try
            classBase.fVullenDataset("SELECT * FROM tbl_sitecontent_menu WHERE submenu='" & intID & "'", "tblRecursiefDelete", DS)

            Dim i, dbAantal, dbCount As Integer
            Dim dbRecord As Data.DataRow

            dbAantal = DS.Tables("tblRecursiefDelete").Rows.Count - 1
            If dbAantal = -1 Then
                Throw New Exception
            Else
                For i = 0 To dbAantal
                    dbRecord = DS.Tables("tblRecursiefDelete").Rows(i)
                    intID = dbRecord("menunummer").ToString
                    arrDelete.Add(intID)

                    If Not dbAantal = dbCount Then
                        dbCount = dbCount + 1
                    End If
                Next i
                RecDelete(intID)
            End If

            Return dbAantal
        Catch ex As Exception
            Return -1
        End Try
    End Function


Iemand nog enkele ideeen ? :S

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
hier klopt dus ook niks van. Je hebt de volgend code
Visual Basic .NET:
1
2
3
4
5
6
7
Function RecDelete(ByVal intID As Integer) As Boolean 
    If Not Me.HasChildren(intID) = -1 Then 
        RecDelete(intID) 
    Else 
        arrDelete.Add(intID) 
    End If 
End Funciton


wat dit doet is
code:
1
2
3
4
5
6
7
8
Function RecDelete( recID )
    If HasChildren
        DeletRecord 'Dit is dus het huidige record omdat je gewoon recID meegeeft
    else
        Voeg het nummertje toe aan een array om later weg te gooien
    end if

    End Function


Wat je moet doen is ongeveer hetvolgende
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void DeleteRecursive( int recID )
{
    int[] childRecords = GetChildren( recID );
    foreach( int childRecord in childRecords )
        DeleteRecursive( childRecord );
    DeleteRecord( recID );
}
private int[] GetChildren( int recID )
{
    //todo: Code om de id's van children op te halen
}
private void DeleteRecord( int recID )
{
    //todo: Code om een record weg te gooien.
}

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”

Pagina: 1