Autor Beitrag
Bennle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 101

WinXP
Delphi 2007 Pro, C# (VS 2005)
BeitragVerfasst: Sa 05.01.08 23:26 
Hallo,
Ich möchte einen einfachen SQL Befehl starten ala "SELECT `name` FROM `user`;" zu einer AccessDB
Nun habe ich bereits die Connection mittels OLEDBConnection aufgebaut, jedoch komme ich nicht wirklich weiter wenn ich die Daten auslesen möchte.

Kann mir jemand einfach mal ein Codebeispiel posten? Es muss keine Begründung dabei sein!

Bitte keine Querverweise auf andere Artikel usw. da ich bereits schon viel gelesen habe (Openbook, Threads usw.) jedoch bin ich nicht weit gekommen.

MfG
Benny

PS: Ich bin ein Umsteiger von Delphi, daher ist es noch etwas ungewohnt für mich.

ERLEDIGT!
Ich habe vergessen ToString() zu verwenden.

Bei Gelegenheit werde ich die Antwort posten!
JüTho
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2021
Erhaltene Danke: 6

Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
BeitragVerfasst: So 06.01.08 13:26 
Hallo,

auch wenn Du das Problem als "erledigt" gekennzeichnet hast, möchte ich Dich auf Folgendes hinweisen:

Weil Du ToString() verwenden wolltest, habe ich den starken Verdacht, dass Du den SELECT-Befehl per String-Verknüpfung zusammengesetzt hast. Davor möchte ich dringend warnen; benutze stattdessen DbParameter, wie ich es z.B. unter Access Datenbanken erläutert habe.

Gruß Jürgen
Bennle Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 101

WinXP
Delphi 2007 Pro, C# (VS 2005)
BeitragVerfasst: So 06.01.08 13:57 
Titel: Ergebnis?!
Ok, danke!

Ich habe es so gemacht:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
//set string
            string connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=database.mdb;";
            //create new Connection
            OleDbConnection con = new OleDbConnection(connectionString);
            OleDbCommand cmd = new OleDbCommand();
            cmd.Connection = con;
            string sql_query = "SELECT * FROM `user`;";
            cmd.CommandText = sql_query;
            OleDbDataAdapter dbda = new OleDbDataAdapter(cmd);
            //open connection
            con.Open();
            DataSet ds = new DataSet();
            dbda.Fill(ds);
           foreach (DataRow row in ds.Tables[0].Rows)
            {
                string str=row["name"].ToString();
                MessageBox.Show(str);
            }


Soll ich etwas ändern? Oder ist das richtig?

Kann ich das ganze eigentlich in eine Funktion packen? (Ich habe bisher nichts derartiges gefunden!)

Bitte ggf. korrigieren.


MfG
Benny
JüTho
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2021
Erhaltene Danke: 6

Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
BeitragVerfasst: So 06.01.08 14:52 
Hallo Bennie,

im Prinzip kann es so gemacht werden.

Es gibt nur einen wirklichen Fehler dabei: die DbConnection wird nur geöffnet, aber nicht geschlossen. Das sollte keinesfalls sein; unter ADO.NET bleibt eine Verbindung nur für einen Befehl geöffnet und wird sofort wieder geschlossen. (Ausnahme: wenn kurz hintereinander mehrere Befehle ausgeführt werden sollen, kann sie vor dem ersten geöffnet und nach dem letzten geschlossen werden.)

Es gibt aber einige ungünstige Verfahren. Ich möchte dies zunächst erläutern und abschließend eine kurze Gesamtlösung bringen.

Die DbConnection sollte nicht nur kurzfristig geöffnet sein, sondern überhaupt nur kurzfristig existieren. (Warum das sinnvoll ist, würde eine lange Diskussion heraufführen; lies lieber die vielen Artikel in der SDK-Doku.) Deshalb ist ein eigenständiger using-Block sinnvoll.

Die Gänsefüßchen bei "user" deuten darauf hin, dass der Name der Tabelle ungünstig gewählt ist, weil "user" auch ein interner Begriff einer DB sein kann. Das kann bei der Formulierung von SQL-Befehlen immer wieder einmal zu Problemen führen. Vielleicht bist Du auch nur daran gewohnt; unter SQL werden Tabellennamen grundsätzlich ohne Anführung geschrieben. (Es gibt Ausnahmen, z.B. bei Verknüpfungen unter MS-SQL mit bestimmten DBs oder bei Sonderzeichen oder ...)

In der Regel werden nicht alle Daten einer Tabelle eingelesen. Gewöhne Dir von Anfang an an, nur die in der konkreten Situation benötigten Zeilen und Spalten zu holen: beispielsweise Nachschlagetabellen und Name/PLZ/Ort eines bestimmten Kunden. (Für eine neue Bestellung interessiert Dich höchstens, dass der Kunde existiert und keine Schulden hat, aber weder sein Geburtstag noch seine Kontonummer...)

Das DataSet wird doch nicht nur für das Einlesen der Daten benötigt, sondern während des gesamten Programmablaufs. Also gehört es nicht zum Datenabruf, sondern in eine eigene Klasse "Datenvorrat" (Suche nach "Singleton"). Durch die IDE kann es auch einem Formular zugeordnet werden; aber das ist unpraktisch, denn dieselben Daten gehören ja meistens zu mehreren Formularen.

Der Zugriff auf einzelne Daten geschieht üblicherweise nicht über ToString() - das ist nur bei der Kontrolle über MessageBox akzeptabel -, sondern über ein cast auf den betreffenden Datentyp:
ausblenden C#-Quelltext
1:
string str = (string)row["name"];					

Vor allem am Anfang des Lernprozesses sind vermutlich typisierte Datasets vorzuziehen; das ist aber ein ganz anderer Themenkomplex.

Bei Verwendung des DbDataAdapters kann con.Open (fast immer - siehe oben) entfallen: dieser öffnet und schließt die Verbindung selbständig.

"in eine Funktion packen": (Unter C# spricht man einheitlich von Methoden.) Selbstverständlich, das geht doch mit allem, was wiederholt benutzt wird. Ich nutze eine eigene Klasse DbConnector, die die Zusammenarbeit mit der DB steuert, mit verschiedenen SQL-Befehlen aufgerufen wird und passende Datenmengen zurückliefert.

Eine Methode (ohne eigene Klasse) kann also so aussehen:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
string commandString = "SELECT * FROM user WHERE ID = ?;";
public void SelectData(DataSet ds, string commandString, int userID) 
{
    string connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=database.mdb;";
    using(OleDbConnection con = new OleDbConnection(connectionString)) {
        OleDbCommand cmd = new OleDbCommand(commandString, con);
        cmd.Parameters.AddWithValue("userid", userID);
        OleDbDataAdapter dbda = new OleDbDataAdapter(cmd);
        dbda.Fill(ds);
     }
}

Einmal programmiert, kann diese Methode in jeder Situation immer wieder neu aufgerufen werden. Lediglich für die flexible Parameter-Übergabe muss man sich deutlich mehr Gedanken machen als ich hier mit diesem Beispiel.

Ich hoffe, ich habe mit meinen Erklärungen geholfen. Jürgen
Bennle Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 101

WinXP
Delphi 2007 Pro, C# (VS 2005)
BeitragVerfasst: So 06.01.08 15:14 
Spitze! Deine Antwort ist einfach super! So präzise. Ich habe mir wohl selbst weniger Gedanken darüber gemacht wie du.

ausblenden C#-Quelltext
1:
cmd.Parameters.AddWithValue("userid", userID)					


Wann und wie wird dieser Parameter zugeordnet? Ich gehe davon aus, dass dieser im commandString das Fragezeichen ersetzt.

Allgemeine Verständissfrage:
Beim Aufruf von SelectData übergebe ich meine Variablen. Gibt es keinen Rückgabewert? Kann ich danach einfach das DataSet verwenden und die Daten sind gesetzt?


MfG
Benny

PS: Der Umstieg ist etwas ungewohnt für mich :)
JüTho
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2021
Erhaltene Danke: 6

Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
BeitragVerfasst: So 06.01.08 18:14 
OpenBook Visual C# Kap.26.3.6 Parametrisierte Abfragen

Das DataSet müsste automatisch als Referenz übergeben werden; alle Änderungen innerhalb der Methode sind deshalb auch nach der Rückkehr bekannt. Falls das nicht klappt (das habe ich mir jetzt nicht überlegt), kannst Du auch explizit die Übergabe als Referenz festlegen (sowohl bei Deklaration als auch beim Aufruf):
ausblenden C#-Quelltext
1:
SelectData(ref MyDataSet, commandString, 17);					

Gruß Jürgen
Bennle Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 101

WinXP
Delphi 2007 Pro, C# (VS 2005)
BeitragVerfasst: So 06.01.08 20:15 
Zitat:
Hinweis Die Odbc- und OleDb-Datenprovider benutzen das Fragezeichen als Platzhalter.


Ok, da ich es leider nicht testen kann (momentan kein VC#) stellt sich mir die Frage wie ich dann mehrere Parameter unterscheide / definiere.

Ich denke das ich so langsam nerfe oder? :D