2016-10-20 3 views
0

Ich bin ein bisschen stecken in gerade jetzt versuchen, die beste Lösung zu bestimmen, um eine unendliche Rekursionsschleife zu verhindern. Vielleicht ist es nicht genau "Rekursion", aber es ist eine Reihe von Funktionsaufrufen, die ich ziemlich garantieren kann, wird sich gegenseitig auf unbestimmte Zeit aufrufen, wenn ich nicht mit einer Lösung kommen kann.VB.NET So verhindern Sie unendliche Rekursion während Objekt Population

Bei dem Versuch, herauszufinden, wie das Problem zu erklären ist, scheint es der beste Weg zu sein, mit etwas vereinfachtem (und redigiertem) Code zu beginnen. In diesem Beispiel verwende ich ein Klassenzimmer und einen Schüler.

Public Class Classroom 
    Public Property ClassroomID As Integer 
    Public Property ClassroomDescription As String 
    Public Property Students As List(Of Student) 

    Public Sub New(ByVal ClassroomID As Integer) 
     Initialize() 
     GetClassroomDetail(ClassroomID) 
    End Sub 

    Public Sub GetClassroomDetail(ByVal ClassroomID As Integer) 
     Dim Reader As SqlDataReader 

     ' HERE'S WHERE I MAKE THE DATABASE CALL TO 
     ' GET THE CLASSROOM RECORD DETAILS 

     FillClassroomRecord(Reader) 
    End Sub 

    Private Sub FillClassroomRecord(Reader) 
     While Reader.Read 
      ClassroomID = CType(Reader("ClassroomID"), Integer) 
      ClassroomDescription = CType(Reader("ClassroomDescription"), String) 

      Students = GetClassroomStudents(ClassroomID) 
     End While 
    End Sub 

    Private Function GetClassroomStudents(ByVal ClassroomID As Integer) As List(Of Student) 
     Dim StudentData As DataTable 
     Dim ClassroomStudents As New List(Of Student) 

     ' I PULL A LIST OF STUDENTS RELATED TO THE SPECIFIC CLASSROOMID 

     For Each StudentRow As DataRow In StudentData.Rows 
      Dim NewStudent As New Student(CType(StudentRow("studentid"), Integer)) 

      ClassroomStudents.Add(NewStudent) 
     Next StudentRow 

     Return ClassroomStudents 
    End Function 
End Class 

Bis jetzt, ziemlich direkt. Das Problem liegt jedoch in der Tatsache, dass der gleiche Schüler an mehrere Klassenzimmer gebunden sein kann. Ich möchte eine ähnliche Methode im Objekt Student haben, um alle zugehörigen Klassenräume für diesen Schüler ziehen zu können.

Public Class Student 
    Public Property StudentID As Integer 
    Public Property Name As String 
    Public Property Classrooms As List(Of Classroom) 
    ... 
    Private Function GetStudentClassrooms(ByVal StudentID As Integer) As List(Of Classroom) 
     Dim ClassroomData As DataTable 
     Dim StudentClassrooms As New List(Of Classroom) 

     ' PULL A LIST OF CLASSROOMS RELATED TO THE SPECIFIC STUDENTID 

     For Each ClassroomRow As DataRow In ClassroomData.Rows 
      Dim NewClassroom As New Classroom(CType(ClassroomRow("classroomid"), Integer)) 

      StudentClassrooms.Add(NewClassroom) 
     Next ClassroomRow 

     Return StudentClassrooms 
    End Function 
End Class 

Also, meine Bestürzung an dieser Stelle ist, wie verhindere ich es von ständig hin und her zwischen den Klassenräumen Looping und den Schülern die gleichen Dinge immer und immer wieder in einer Endlosschleife bevölkern?

Das einzige, was ich mir vorstellen kann, ist eine boolesche Variable irgendwo zu setzen, die ich einstellen kann, um zu bestimmen, ob ich weiter bohren soll oder nicht. Das Problem ist, dass mein Gehirn im Moment ein wenig gebraten ist und ich nicht herausfinden kann, wie man eine solche Lösung implementiert.

Einige der Recherchen, die ich gemacht habe, erwähnten auch die Möglichkeit einer Art "Backtracking", was cool klingt, aber in dieser Art von Situation nicht sehr wahrscheinlich funktioniert. Natürlich könnte ich darin falsch liegen, und ich würde gerne irgendeine Art von Implementierung sehen, die irgendwie in der Lage ist, intelligent zu identifizieren, wenn ich die gleichen Dinge immer und immer wieder in die gleiche Schleife bringe.

Was Ich mag würde, um zu sehen geschehen ist die Top-Level-Classroom Objekterstellung sollte seine Student Gegenstände aufnehmen, die alle zusätzlichen Classroom Objekte abholen sollte, an die sie verbunden sind, einschließlich jedes dieser ClassroomStudent Objekte des Objekts, und dann hört es auf.

Ich hoffe, dass alles einen Sinn ergibt. Es ist sogar noch komplizierter als das, da es andere ähnliche Objekte gibt, die an das Objekt auf der obersten Ebene gebunden werden (Classroom), das ebenfalls denselben Grundregeln folgen sollte - nicht zu tief in die "Unter" -Daten graben, und verhindern Sie eine unendliche rekursive Schleife

Wenn irgendeine Klärung notwendig ist, lass es mich wissen. Ich schätze wirklich jede Hilfe, die Sie zur Verfügung stellen können.

+1

Warum hätte ein 'ClassRoom' Interesse an den anderen' ClassRoom'-Objekten? –

+0

Wenn ich Ihre Frage verstehe, ist die Antwort "Nein". Nicht in dem Sinne, dass ein "Klassenzimmer" das andere "Klassenzimmer" kennen müsste, existiert * an sich *. Nur wie es sich auf den 'Student' bezieht. –

+1

Ihre Klassen sind ein bisschen überreizt. Jedes Klassenzimmer benötigt keine Liste von Schülern - eine Liste von Ids, die die Schüler repräsentieren, ist genug. 'GetClassroomStudents' erstellt neue Studenten anstatt eine Liste der aktuellen Studenten aus einer Sammlung von ihnen zu bekommen. Wenn Sie Ihre Liste wiederholen würden, um einige abwesende oder festgelegte Noten zu markieren, würde dies für eine andere Schülergruppe als für die Haupt-/Hauptsammlung gelten. Ansonsten erleichtert linq das Extrahieren von Sätzen basierend auf dieser oder jener Eigenschaft. – Plutonix

Antwort

0

Ich denke, ich habe vielleicht eine Idee, wie ich das lösen könnte, aber ich würde gerne ein Feedback zu meiner Idee bekommen.

Wenn ich eine Überlastung des New Konstruktor erstellen, die einen booleschen Wert (GetRelatedDetails) annimmt, dann kann ich es nennt zunächst mit diesem Flag auf True. Fast alles andere sollte gleich bleiben, außer dass dieser Wert in der Kette weitergegeben wird.Im obigen Beispiel würde es in etwa so aussehen:

Public Class Classroom 
    Public Property ClassroomID As Integer 
    Public Property ClassroomDescription As String 
    Public Property Students As List(Of Student) 

    Public Sub New(ByVal ClassroomID As Integer) 
     Initialize() 
     GetClassroomDetail(ClassroomID, False) 
    End Sub 

    ' OVERLOAD WITH BOOLEAN VALUE TO GET RELATED DETAILS 
    Public Sub New(ByVal ClassroomID As Integer, ByVal GetRelatedDetails As Boolean) 
     Initialize() 
     GetClassroomDetail(ClassroomID, GetRelatedDetails) 
    End Sub 

    Public Sub GetClassroomDetail(ByVal ClassroomID As Integer, ByVal GetRelatedDetails As Boolean) 
     Dim Reader As SqlDataReader 

     ' HERE'S WHERE I MAKE THE CALL TO GET THE 
     ' CLASSROOM RECORD DETAILS FROM THE DATABASE 

     FillClassroomRecord(Reader, GetRelatedDetails) 
    End Sub 

    Private Sub FillClassroomRecord(ByVal Reader As SqlDataReader, ByVal GetRelatedDetails As Boolean) 
     While Reader.Read 
      ClassroomID = CType(Reader("ClassroomID"), Integer) 
      ClassroomDescription = CType(Reader("ClassroomDescription"), String) 

      If GetRelatedDetails Then 
       Students = GetClassroomStudents(ClassroomID) 
      End If 
     End While 
    End Sub 

    Private Function GetClassroomStudents(ByVal ClassroomID As Integer) As List(Of Student) 
     Dim StudentData As DataTable 
     Dim ClassroomStudents As New List(Of Student) 

     ' I PULL A LIST OF STUDENTS RELATED TO THE SPECIFIC CLASSROOMID 

     For Each StudentRow As DataRow In StudentData.Rows 
      Dim NewStudent As New Student(CType(StudentRow("studentid"), Integer)) 

      ClassroomStudents.Add(NewStudent) 
     Next StudentRow 

     Return ClassroomStudents 
    End Function 
End Class 

Dann wird das Student Objekt tut im Grunde das Gleiche:

Public Class Student 
    Public Property StudentID As Integer 
    Public Property StudentName As String 
    Public Property Classrooms As List(Of Classroom) 

    Public Sub New(ByVal StudentID As Integer) 
     Initialize() 
     GetStudentDetail(StudentID, False) 
    End Sub 

    ' OVERLOAD WITH BOOLEAN VALUE TO GET RELATED DETAILS 
    Public Sub New(ByVal StudentID As Integer, ByVal GetRelatedDetails As Boolean) 
     Initialize() 
     GetStudentDetail(StudentID, GetRelatedDetails) 
    End Sub 

    Public Sub GetStudentDetail(ByVal StudentID As Integer, ByVal GetRelatedDetails As Boolean) 
     Dim Reader As SqlDataReader 

     ' HERE'S WHERE I MAKE THE CALL TO GET THE 
     ' STUDENT RECORD DETAILS FROM THE DATABASE 

     FillStudentRecord(Reader, GetRelatedDetails) 
    End Sub 

    Private Sub FillStudentRecord(ByVal Reader As SqlDataReader, ByVal GetRelatedDetails As Boolean) 
     While Reader.Read 
      StudentID = CType(Reader("StudentID"), Integer) 
      StudentName = CType(Reader("StudentName"), String) 

      If GetRelatedDetails Then 
       Classrooms = GetStudentClassrooms(StudentID) 
      End If 
     End While 
    End Sub 

    Private Function GetStudentClassrooms(ByVal StudentID As Integer) As List(Of Classroom) 
     Dim ClassroomData As DataTable 
     Dim StudentClassrooms As New List(Of Classroom) 

     ' PULL A LIST OF CLASSROOMS RELATED TO THE SPECIFIC STUDENTID 

     For Each ClassroomRow As DataRow In ClassroomData.Rows 
      Dim NewClassroom As New Classroom(CType(ClassroomRow("classroomid"), Integer)) 

      StudentClassrooms.Add(NewClassroom) 
     Next ClassroomRow 

     Return StudentClassrooms 
    End Function 
End Class 

Sie feststellen, dass würden, auch wenn ich in einem Wert übergeben von True zu dem ursprünglichen Objekt, wenn es an die Fill Methode gelangt, und tritt in die GetClassroomStudents oder GetStudentClassrooms, ruft es nur die New Konstruktorüberladung, die standardmäßig auf False. Auf diese Weise vermute ich, dass es verhindern sollte, dass es immer wieder dieselben Datensätze durchläuft.

Natürlich bin ich offen für alle anderen Vorschläge oder Ideen über die beste Art und Weise, dies zu implementieren, aber ich denke, das ist, was ich für jetzt tun werde.

Verwandte Themen