Laden...

TreeView Nodes Füllen

Erstellt von SoHeLL vor 19 Jahren Letzter Beitrag vor 19 Jahren 7.112 Views
SoHeLL Themenstarter:in
62 Beiträge seit 2004
vor 19 Jahren
TreeView Nodes Füllen

Hallo,

ich würde gerne 2 Ebenen von Nodes von der Datenbank befüllen lassen.

Genauer:
Der erste Child-Node soll z.B. den Verlag aus der Datenbank auslesen und sie anzeigen und in einer neuen Schleife (bis reader.read() false ergibt) sollen die Bücher des Verlages ausgelesen und angezeigt werden.

Fragestellung:
wie mach ich sowas mit einem DataSet bzw. mit dem ADO.NET Prinzip (also mit Connection, Adapter und dataSet).

Fehler:
Habe versucht einfach die SQL Anweisung zu verändern.
z.B.:
SELECT buch.buchNr, verlag.buchNr, buchbezeichnung, verlagNr, verlagName FROM buch, verlag where buch.buchNr = verlag.buchNr

Dann stürzt aber dann das Programm ab. Im Debugger erscheit die Fehlermeldung "Eine nicht behandelte Ausnahme des Typs 'System.IndexOutOfRangeException' ist in system.data.dll aufgetreten.

Zusätzliche Informationen: verein.VereinsNr"


while(Reader.Read())
{
// in der kommenden ZEILE meldet der Debugger die Meldung!
TreeNode unterast = new TreeNode("#" + Reader["verlag.VereinsNr"].ToString()+" " + Reader["verlag.verlagName"].ToString());
unterast.Tag = Reader["verlagNr"];
Oberast.Nodes.Add(unterast);
}

Ich hoffe, dass mir geholfen werden kann!
Danke
Soheil


Ich Danke im Voraus SoHeLL

S
127 Beiträge seit 2004
vor 19 Jahren

Hi,

ein Reader kann nur einmal die Daten durchlaufen, und wenn die Verbindung zu ist dann wird der Inhalt auch gelöscht (denke ich zumindestens).

Mein Vorschlag wäre:
(davon gehe ich mal aus, das du hast zwei Tabellen die durch eine Relation verbunden sind. In der einen Tabelle sind alle Verlage drin und in der zweiten sind alle Bücher drin und ein Schlüssel der auf den Verlag verweist.)

Bei dieser Situation würde ich dir ein DataSet mit Relationen empfehlen. So brauchst du nur die Verlagtabelle durch gehen. Da jede Zeile der Verlagtabelle weiss welche Bücherzeile zu ihr gehört.


public void FillTree_Root( myDataSet arg)
{
 TreeNode aNode;
 foreach(myDataSet.VerlagRow aRow in (myDataSet.VerlagRow)arg.Verlag.Rows)
{
    
   aNode = new TreeNode(aRow.Verlagname);
    FillTree_Child(aRow.getBuecherRows(), aNode);
    myTreeView.add(aNode);
}
}

public void FillTree_Child(DataRow[] theRows, TreeNode theNode)
{
TreeNode aNode;
foreach(DataRow aRow in theRows)
{
    aNode = new TreeNode(aRow["Buechertitel"].toString());
    theNode.add(aNode);
}
}

So jetzt zur Frage wie erstelle man so ein DataSet. siehe hier Exemplarische Vorgehensweise: Erstellen von Datasets mit Tabellen, Schlüsseln und 1:n-Beziehungen
Was ich in dem Beispeil verwendet habe ist ein typersiertes DataSet, wie man dieses erstellt siehe hier Erstellen neuer typisierter Datasets mit dem XML-Designer

Und nun zur Datenbank Anbindung
Das ist abhängig von der verwendeten Datenbank, im Prinzip sind sie aber alle gleich. Du musst nur die entsprechenden Klassen ansprechen. (hier ist es für den SQL-Server)


SqlConnection SqlConn = new SqlConnection(ConnectionString);
SqlConn.Open();
SqlDataAdapter SqlAdapter = new SqlDataAdapter(SelectString, SqlConn);
SqlAdapter.Fill(<DataSet oder Tabelle die gefüllt werden soll>,TabellennameString);
SqlConn.Close();

ich hoffe das ich dir helfen konnte 🙂

SoHeLL Themenstarter:in
62 Beiträge seit 2004
vor 19 Jahren

Danke für deine Hilfe. Aber es scheint nicht zu funktionieren.

Ich hab mal die ODBC Schnittstelle benuzt. Und habe auch noch ein DataSet1 erstellt.
Aber ich versuch mal das was ich verstanden habe in c# Code auszudrücken:X(


System.Data.Odbc.OdbcConnection Connection = new System.Data.Odbc.OdbcConnection ("DSN=Microsoft Access-Datenbank;DefaultDir=C:\\;DriverId=25;DBQ=C:\\Datenbank.mdb;Ma" +
"xBufferSize=2048;FIL=MS Access;PageTimeout=5;UID=admin";);
System.Data.Odbc.OdbcDataAdapter Adapter = new System.Data.Odbc.OdbcDataAdapter("
SELECT buch.buchNr, verlag.buchNr, buchbezeichnung, verlagNr, verlagName FROM buch, verlag where buch.buchNr = verlag.buchNr",Connection);
Adapter.Fill(Dataset1,buch);
Connection.Open();
TreeNode aNode;
foreach(myDataSet.VerlagRow aRow in (myDataSet.VerlagRow)arg.Verlag.Rows)
{
aNode = new TreeNode(aRow.Verlagname);
TreeNode anotherNode;
FillTree_Child(aRow.getBuecherRows(), aNode);
myTreeView.add(aNode);
}
// weiter unten
public void FillTree_Child(DataRow[] theRows, TreeNode theNode)
{
foreach(DataRow aRow in theRows)
{
anotherNode = new TreeNode(aRow["buchbezeichnung"].toString());
aNode.add(anotherNode);
}

Und was mach ich hier falsch?


Ich Danke im Voraus SoHeLL

S
127 Beiträge seit 2004
vor 19 Jahren

Ist das DataSet ein typerisiertes DataSet?

Aber un abhängig davon benutze reine Sql-Statments
"Select * From verlag" und "Select * From buch".



public static void main(String[] args)
{
DataSet aDs = new myDataSet(); // typerisertes DataSet erstellen
//DataSet aDs = new DataSet(); Fehler -> erstellt ein normales DataSet
LoadSql("Select * From verlag","Verlag",aDs); // von der Datenbank die Tabelle Verlag holen
LoadSql("Select * From buch","Buch",aDs); // von der Datenbank die Tabelle Buch holen
FillTree_Root(aDs) // TreeView füllen
}

public void FillTree_Root( myDataSet arg)
{
TreeNode aNode; // neuen Knoten erstellen
foreach(myDataSet.VerlagRow aRow in (myDataSet.VerlagRow)arg.Verlag.Rows)
// die Verlagstabelle durch gehen und für jeden Verlag einen Eintrag machen
{
aNode = new TreeNode(aRow.Verlagname);

// die entsprechenden Buecher aus dem Verlag als Unterknoten dem Verlag zuweisen
FillTree_Child(aRow.getBuecherRows(), aNode);

// den Verlag dem Steuerelement <TreeView> zuweisen
myTreeView.add(aNode);
}
}

public void FillTree_Child(DataRow[] theRows, TreeNode theNode)
{
TreeNode aNode; // neuen Unterknoten erstellen
foreach(DataRow aRow in theRows)
// durch das Array durch gehen und für jeden Eintrag einen neuen Unterknoten anlegen
{
aNode = new TreeNode(aRow["Buechertitel"].toString()); // neuer Unterknoten

// den neuen Unterknoten dem Verlag zuweisen
theNode.add(aNode); 
}
}


public void LoadSql(String sql, String table, DataSet Ds)
{
try
// ein try-catch um Fehler bei holen der Daten abzufangen
{
// neues Verbindungsobjekt erstellen
System.Data.Odbc.OdbcConnection Connection = new System.Data.Odbc.OdbcConnection ("DSN=Microsoft Access-Datenbank;DefaultDir=C:\\;DriverId=25;DBQ=C:\\Datenbank.mdb;Ma" +
"xBufferSize=2048;FIL=MS Access;PageTimeout=5;UID=admin");

// Verbindung öffnen
Connection.Open();

// neuen Adapter erstellen mit dem Sql für die benötigen Daten und dem Verbindungsobjekt
System.Data.Odbc.OdbcDataAdapter Adapter = new System.Data.Odbc.OdbcDataAdapter(sql,Connection);

// Daten aus der Datenbank in das DataSet ziehen, und Tabellennamen dafür vergeben
Adapter.Fill(Ds,table);
}
catch(OdbcException ex)
{

// falls Fehler bitte Meldung an USER
Messagebox.Show(ex.Message);
}
finally
{

// auf jeden Fall zu Schluss die Verbindung wieder schließen, auch bei einem Fehler
Connection.Close();
}
}

der Code sollte eigentlich funz, versuche ihn mal zu Debugen Schritt für Schritt und überlege was er beim nächsten Schritt machen soll und ich denke dann kommt das Verständnis von ganz allein.

Wenn du Fragen hast, dann Frage

SoHeLL Themenstarter:in
62 Beiträge seit 2004
vor 19 Jahren

Hi,

Ich entschuldige mich für einen so späten Feedback.

Aber hier erst einmal die Fehlermeldung:

Der Typ oder Namespace 'myDataSet' konnte nicht gefunden werden. Möglicherweise fehlt eine Anweisung oder ein Assemblyverweis.

Danke
Soheil


Ich Danke im Voraus SoHeLL

N
4.644 Beiträge seit 2004
vor 19 Jahren

Hast Du die Anweisung using System.Data; eingebunden?

@suny
Warum ist

DataSet aDs = new DataSet(); // typerisertes DataSet erstellen

ein typisiertes DataSet bzw. warum soll es das sein?

S
127 Beiträge seit 2004
vor 19 Jahren

Entschuldige das ich mich erst so spät melde.

Ein typerisiertes DataSet ist ein spezielles DataSet das die Datenbankstrucktur kennt. Also welche Spalte ist Primary Key wie sehen die Relationen zwischen den Tabellen aus und welche Spalte ist Foreign Key. Zusätzlich kennt es auch noch andere Constranst der Datenbank wie Unique, darf nicht Null sein, u.s.w. .

Da mit lässt sich im Programm schön arbeiten. Ich glaube das hätte ich am Anfang erklären sollen.

Ich habe in meinen ersten Post ja auch zwei Links erstellt die erklären wie man so etwas macht.

Um das Problem zulösen muss man kein typerisiertes DataSet benutzen, aber es ist einfach schöner mit. Man muss nicht aufwendige Suchfunktionen schreiben die die untergeordneten Elemente wieder geben. Und einfach immer wieder eine Abfrage an die Datenbank legt das Netzwerk lahm, zumindestens wenn mehrere Client das Programm benutzen.

N
4.644 Beiträge seit 2004
vor 19 Jahren

Ich weiß, was ein typisiertes DataSet ist.
Deine Zeile ist es jedenfalls nicht, es ist lediglich eine Instanz der Klasse DataSet.

Bevor ein typisiertes DataSet erzeugt werden kann, muss zunächst einmal ein XML-Schema vorliegen, dass die Struktur zumindest einer Tabelle der ausgewählten Datenbank repräsentiert.