Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
"Best practice" gesucht: Hierarchie
Bini
myCSharp.de - Member

Avatar #avatar-1555.jpg


Dabei seit:
Beiträge: 195
Herkunft: der wilde Osten

Themenstarter:

"Best practice" gesucht: Hierarchie

beantworten | zitieren | melden

Hallo Leutz,

ich muß Daten in einem TreeView darstellen, die in einer beliebig tiefen Hierarchie ineinander verschachtelt sind. Zu Beginn werden nur die Top-Nodes angezeigt und die darunter liegenden Daten erst beim Auswählen eines Node nachgeladen.

Beim Starten der Anwendung wird aus der DB gelesen, auf welchem Knoten sich der Nutzer beim Schließen des Programms befand und dieser Knoten soll wieder selektiert werden.

Dazu muß ich von jedem Unterknoten wissen, an welchem Top-Node er hängt, egal, wieviele Level sich dazwischen befinden.

Im Moment wird jedesmal eine hierarchische Query ausgeführt (Oracle). Das sieht zwar hübsch aus, ist aber nicht allzuschnell.

Ich möchte die Information "Top-Node" irgendwie bewahren und nicht jedesmal raussuchen, zumal die sich nicht sehr häufig ändert.

Ich könnte die Tabelle um ein Feld erweitern und das dort reinschreiben.

Ich könnte einen Snapshot anlegen.

Gibt's noch andere Möglichkeiten?

Wie würdet Ihr das machen bzw. wie macht Ihr das?
Umwege erhöhen die Ortskenntnis.
private Nachricht | Beiträge des Benutzers
svenson
myCSharp.de - Member



Dabei seit:
Beiträge: 8.746
Herkunft: Berlin

beantworten | zitieren | melden

Tree komplett auslesen und im Speicher cachen? Hierarchische DB verwenden?

Ist nunmal ein undankbares Problem für relationale DBs, die kommen mit hierarchischen oder rekursiven Strukturen schlecht zurecht....
private Nachricht | Beiträge des Benutzers
Bini
myCSharp.de - Member

Avatar #avatar-1555.jpg


Dabei seit:
Beiträge: 195
Herkunft: der wilde Osten

Themenstarter:

beantworten | zitieren | melden

> Tree komplett auslesen und im Speicher cachen

Ist zu groß. Bin ich grad davon weggekommen...

> Hierarchische DB verwenden

Zu viel Aufwand.
Umwege erhöhen die Ortskenntnis.
private Nachricht | Beiträge des Benutzers
citizen.ron
myCSharp.de - Member

Avatar #avatar-1693.jpg


Dabei seit:
Beiträge: 432
Herkunft: Frankfurt / Main

beantworten | zitieren | melden

hi bini,

in vs2005 / .net 2.0 kennt jeder knoten seinen toplevelnode über FirstNode. bist du noch in 2003? gab´s das da noch nicht?

hth, ron
private Nachricht | Beiträge des Benutzers
Programmierhans
myCSharp.de - Experte

Avatar #avatar-1651.gif


Dabei seit:
Beiträge: 4.221
Herkunft: Zentralschweiz

beantworten | zitieren | melden

Ueber Node.FullPath erhälst Du auch den ganzen Pfad.... diesen kannste dann mit string.Split am TreeView.PathSeparator splitten .... dann hast Du die ganze Hierarchie...

Zudem kannst Du Dir eine eigene TreeNode-Klasse bauen die z.B: die PrimaryKeys .. oder den "Ausführweg um an die Daten zu kommen" zwischenspeichert.

Falls Du noch Hilfe brauchst beim verzögerten laden der Daten in den Tree schau Dir mal folgendes an...

FileTreeView

FileBrowser / Images in X Controls
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
private Nachricht | Beiträge des Benutzers
Bini
myCSharp.de - Member

Avatar #avatar-1555.jpg


Dabei seit:
Beiträge: 195
Herkunft: der wilde Osten

Themenstarter:

beantworten | zitieren | melden

Zitat
Original von citizen.ron
in vs2005 / .net 2.0 kennt jeder knoten seinen toplevelnode über FirstNode. bist du noch in 2003?
*Ähm* *Räusper*
Ich bin noch in VS.2002

Ich meinte aber den Schritt VOR der Erstellung von Nodes. Ich muß ja erst mal die Daten aus der Datenbank holen. Es wird immer ein ganzer Zweig geholt und zwar aus verschiedenen Tabellen. Knoten können Knoten der eigenen Art oder Blätter aus anderen Tabellen enthalten:
- hole die Hierarchie von Elementen "A"
- hole alle Elemente "B", die irgendwo an diesem "A"-Zweig hängen
- hole alle Elemente "C", die irgendwo in diesem "A"-Zweig an den Elementen "B" hängen

Wenn die Daten im Dataset sind, wird aus ihnen der TreeView erstellt.

Aber um das alles zu selektieren, muß ich erst mal den obersten Key des Hierarchie-Zweiges bestimmen - und genau das will ich "abkürzen".
Umwege erhöhen die Ortskenntnis.
private Nachricht | Beiträge des Benutzers
Bini
myCSharp.de - Member

Avatar #avatar-1555.jpg


Dabei seit:
Beiträge: 195
Herkunft: der wilde Osten

Themenstarter:

beantworten | zitieren | melden

Zitat
Original von Programmierhans
Ueber Node.FullPath erhälst Du auch den ganzen Pfad....
Wie ich schon an Ron geantwortet habe - es geht mehr um den Schritt davor
Aber danke für den Link, das Problem mit den FakeNodes hatte ich bisher als nicht vordringlich ignoriert, das werde ich mir mal genauer anschauen.
Umwege erhöhen die Ortskenntnis.
private Nachricht | Beiträge des Benutzers
Programmierhans
myCSharp.de - Experte

Avatar #avatar-1651.gif


Dabei seit:
Beiträge: 4.221
Herkunft: Zentralschweiz

beantworten | zitieren | melden

Bei einem Tree:

A1---B1
B2--C1

hat C1 den Pfad (absichtlich mit Slash statt Backslash... sonst mampft das Forum diese weg) A1/B2/C1

Bei einem Split auf "/" ist das Element 0 des Splits A1 und das hast Du doch gesucht.... oder hab ich da was nicht verstanden ?
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
private Nachricht | Beiträge des Benutzers
Bini
myCSharp.de - Member

Avatar #avatar-1555.jpg


Dabei seit:
Beiträge: 195
Herkunft: der wilde Osten

Themenstarter:

beantworten | zitieren | melden

Zitat
Original von Programmierhans
Bei einem Split auf "/" ist das Element 0 des Splits A1 und das hast Du doch gesucht.... oder hab ich da was nicht verstanden ?
Es ist eher eine DB-Frage. Daß ich damit einen TreeView erstellen will, war eher als Hintergrund-Info gedacht Beim Selektieren der Daten hab ich ja noch keinen TreeView.

Ich könnte auch sagen: die Statements dauern zu lange, weil ich z.B. jedesmal erst den Top-Key von dem Datensatz suchen muß, auf dessen Knoten der Nutzer beim Schließen des Programmes stand, damit ich überhaupt die Daten dieses Zweiges komplett selektieren kann.

Ich kenne kein deutschsprachiges DB-Forum, deshalb hab ich jetzt der Faulheit halber hier gefragt, ich könnte mir vorstellen, daß die Problematik relativ verbreitet ist.
Umwege erhöhen die Ortskenntnis.
private Nachricht | Beiträge des Benutzers
Pulpapex
myCSharp.de - Member



Dabei seit:
Beiträge: 939
Herkunft: Rostock

beantworten | zitieren | melden

Falls das Datenmodell noch geändert werden kann, es gibt eine sehr elegante Möglichkeit Bäume in Tabellen abzubilden.

Hatte Noodles mir mal gezeigt, das Datendesign nennt sich "Nested Sets". Der grosse Vorteil: man kann mit einer einzigen SQL-Anfage einen kompletten Teilbaum laden. Oder man kann mit einer Anfrage zählen lassen, wieviele Knoten ein Teilbaum hat. Oder man kann sich den Pfad von der Wurzel zu einem Knoten geben lassen usw.

Intern basiert das Ganze auf einer Pre-Order Anordnung der Baumknoten. SQL-Anfragen laden quasi Teilbereiche aus dieser Pre-Order Anordnung. Aus der geladenen Liste kann der Teilbaum rekonstruiert werden.

Nachteil bei "Nested Sets" ist der Aufwand bei Änderungen. Um ein Element einzufügen oder einen Teilbaum zu löschen, müssen alle in der Pre-Order Reihenfolge nachfolgenen Baumknoten per SQL-Update aktualisiert werden. Das benötigt zwar selbst nur 2 SQL-Anweisungen - 1. nachfolgende Knoten verschieben (Platz schaffen für einen neuen Knoten schaffen oder frei gewordene Lücke schliessen), 2. Knoten einfügen oder löschen - das ist aber dennoch sehr aufwändig.

Kannst du dir ja mal angucken:
- Googlen nach "Nested Sets"
- Das 'Nested Sets' Modell - Bäume mit SQL


Gruss
Pulpapex
private Nachricht | Beiträge des Benutzers
Programmierhans
myCSharp.de - Experte

Avatar #avatar-1651.gif


Dabei seit:
Beiträge: 4.221
Herkunft: Zentralschweiz

beantworten | zitieren | melden

Das musst Du doch eh weil Du den C1 selektieren willst. Dieser kann aber nur selektiert werden wenn A1 und B2 aufgeklappt sind..... sobald aber A1 aufgeklappt ist müssen ja alle Kinder von A1 angezeigt werden (die musst Du somit zwingend laden)


Du wirst also von A1 ausgehend eh alles darunterliegende (1 Stufe) laden müssen.


Vorschlag:

Du lädst die erste Stufe in den TreeView mit den Fake-Nodes

Dann splittest Du beim Separator und erhälst

[0] A1
[1] B2
[2] C1

nun loopst Du durch dieses Array ...

A1 --> expandieren (dadurch werden die Kinder von A1 nachgeladen)
B2 --> expandieren (dadurch werden die Kinder von B2 nachgeladen)
C1 --> selektieren


Nun sind alle Subnodes der jeweils ersten Stufe unter dem entsprechenden Parent expanded.
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
private Nachricht | Beiträge des Benutzers
Bini
myCSharp.de - Member

Avatar #avatar-1555.jpg


Dabei seit:
Beiträge: 195
Herkunft: der wilde Osten

Themenstarter:

beantworten | zitieren | melden

Zitat
Original von Pulpapex
Falls das Datenmodell noch geändert werden kann...
Nachteil bei "Nested Sets" ist der Aufwand bei Änderungen
Das Datenmodell muß bleiben.
Es werden auch täglich neue Daten erzeugt, es gibt also viele Änderungen. Deshalb fällt ein Snapshot eigentlich auch aus.

Ich werde wohl nicht drumherum kommen, zu den betroffenen Tabellen ein Top-Key-Feld hinzuzufügen... Ich denke mal, der Aufwand ist bei der Lösung doch am geringsten.
Umwege erhöhen die Ortskenntnis.
private Nachricht | Beiträge des Benutzers
Bini
myCSharp.de - Member

Avatar #avatar-1555.jpg


Dabei seit:
Beiträge: 195
Herkunft: der wilde Osten

Themenstarter:

beantworten | zitieren | melden

Zitat
Original von Programmierhans
Das musst Du doch eh weil Du den C1 selektieren willst...
Du meinst den Top-Key suchen? Klar, das muß ich. Aber ich will nicht jedesmal ein hierarchisches Select haben, sondern den irgendwo physisch vorselektiert "parken".

Ich hab zwar viele Änderungen in diesen Tabellen, aber der Top-Key eines einmal erstellten Datensatzes von B und C ändert sich eher selten. Der Verwaltungsaufwand wäre also gering, dieses Feld auf einem aktuellen Stand zu halten.

Es geht NICHT um die Erzeugung des TreeViews
Umwege erhöhen die Ortskenntnis.
private Nachricht | Beiträge des Benutzers
Programmierhans
myCSharp.de - Experte

Avatar #avatar-1651.gif


Dabei seit:
Beiträge: 4.221
Herkunft: Zentralschweiz

beantworten | zitieren | melden

Zitat
Original von Bini

Ich werde wohl nicht drumherum kommen, zu den betroffenen Tabellen ein Top-Key-Feld hinzuzufügen... Ich denke mal, der Aufwand ist bei der Lösung doch am geringsten.

Das Top-KeyFeld wird dir nicht genügen.... sonst musst Du ja von allen Zwischenstufen alles nachladen .... dann lädst Du ja folgendes ein


A1 alle SubNodes B von A1
B1 alle SubNodes C von B1
B2 alle SubNodes C von B2
C1


Dies weil Du nicht weisst wo C1 dranhängt wenn Du auf Stufe B bist.

Die letzte Selektion würde ich nicht auf der DB abspeichern sondern lokal (den FullPath) des Selektierten Nodes.... beim Start der Anwendung wird versucht den Node wieder zu selektieren (Fehlertolerant falls es den Node gar nicht mehr gibt).


Bei der von mir aufgezeigten Lösung müss die Subnodes von B1 nicht geladen werden, da ja nur die SubNodes unter B2 interessant sind (dort hängt ja C dran).
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
private Nachricht | Beiträge des Benutzers
Programmierhans
myCSharp.de - Experte

Avatar #avatar-1651.gif


Dabei seit:
Beiträge: 4.221
Herkunft: Zentralschweiz

beantworten | zitieren | melden

Zitat
Original von Bini

Es geht NICHT um die Erzeugung des TreeViews

Egal. Ob es um eine Darstellung im TreeView oder nur um die logische hierarchische Datenstruktur geht. Wichtig ist, dass Du die Hierarchie und nicht nur den Top-Knoten speicherst. (Ausser Du willst Daten beziehen die nicht von Relevanz sind).
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
private Nachricht | Beiträge des Benutzers
Bini
myCSharp.de - Member

Avatar #avatar-1555.jpg


Dabei seit:
Beiträge: 195
Herkunft: der wilde Osten

Themenstarter:

beantworten | zitieren | melden

Zitat
Original von Programmierhans
sonst musst Du ja von allen Zwischenstufen alles nachladen ....
Ja, genau das will ich auch
Ich will immer einen ganzen Zweig laden, weil meistens mit allen Daten eines Zweiges gearbeitet wird und die Nutzer sowieso alle diese Daten auf einen Schlag brauchen.
Umwege erhöhen die Ortskenntnis.
private Nachricht | Beiträge des Benutzers
Programmierhans
myCSharp.de - Experte

Avatar #avatar-1651.gif


Dabei seit:
Beiträge: 4.221
Herkunft: Zentralschweiz

beantworten | zitieren | melden

Zitat
Original von Bini
Zitat
Original von Programmierhans
sonst musst Du ja von allen Zwischenstufen alles nachladen ....
Ja, genau das will ich auch

Ach so :-)

Dann genügt es aber wenn Du eine Tabelle anlegst:

User SelektierterKnoten RootNode

XY C1 A


So hast Du nicht zusätzliche Abhängigkeiten auf Der DB die auch gepflegt werden müssen..... Falls der C1 auf der DB nicht mehr existiert (und nur dann) musst Du halt wieder über Parent-Parent... auf die Suche nach dem Root-Node gehen.
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
private Nachricht | Beiträge des Benutzers
Bini
myCSharp.de - Member

Avatar #avatar-1555.jpg


Dabei seit:
Beiträge: 195
Herkunft: der wilde Osten

Themenstarter:

beantworten | zitieren | melden

Zitat
Original von Programmierhans
Dann genügt es aber wenn Du eine Tabelle anlegst:

User SelektierterKnoten RootNode

Hm, das wäre eine Idee
So eine Tabelle hab ich ja schon, die müßte ich nur erweitern...

Mal schauen.
Umwege erhöhen die Ortskenntnis.
private Nachricht | Beiträge des Benutzers