communityWir suchen ständig neue Tutorials und Artikel! Habt ihr selbst schonmal einen Artikel verfasst und seid bereit dieses Wissen mit der Community zu teilen? Oder würdet ihr gerne einmal über ein Thema schreiben das euch besonders auf dem Herzen liegt? Dann habt ihr nun die Gelegenheit eure Arbeit zu veröffentlichen und den Ruhm dafür zu ernten. Schreibt uns einfach eine Nachricht mit dem Betreff „Community Articles“ und helft mit das Angebot an guten Artikeln zu vergrößern. Als Autor werdet ihr für den internen Bereich freigeschaltet und könnt dort eurer literarischen Ader freien Lauf lassen.

Verbindung zum MySQL-Server mit C# PDF Drucken E-Mail
Benutzerbewertung: / 394
SchwachPerfekt 
Geschrieben von: StarShaper   
Samstag, den 08. April 2006 um 11:01 Uhr

Einführung

MySQL ist ein beliebtes SQL-Datenbankverwaltungssystem und als Open-Source-Software für verschiedene Betriebssysteme verfügbar. Besonders häufig wird MySQL für Webauftritte genutzt. Insbesondere die Tatsache das es sich bei MySQL um ein hochperformantes Datenbanksystem handelt und es für nicht kommerzielle Nutzungen unter die GPL fällt, macht es interessant. Leider stellt Microsoft in seinem .NET Framework keinen ADO.NET Treiber für MySQL zur Verfügung. Dies ist wohl darin begründet das Microsoft bestrebt ist sein eigenes relationales Datenbanksystem namens Microsoft SQL Server zu vermarkten.

In diesem Tutorial werde ich die gängigen Methoden vorstellen mit denen jeder auf einfache Art .NET Applikationen erstellen kann, die in der Lage sind mit einem MySQL Server zu kommunizieren. Es existieren zwei gängige Varianten die sehr häufig zum Einsatz kommen. Die eine Variante nutzt einen ODBC Treiber namens MyODBC. Die ODBC Spezifikation stellt eine prozedurale API für die Nutzung von SQL Queries zum Datenzugriff zur Verfügung. Die andere Variante nutzt einen ADO.NET Treiber der explizit für die MySQL Kommunikation unter .NET entwickelt wurde. Der Treiber ist vollständig in C# geschrieben und der Quellcode ist offen.

Der MySQL Connector/Net implementiert die benötigten ADO.NET Schnittstellen und integriert sich daher problemlos in entsprechende Tools die die ActiveX Data Objects Technologie nutzen. Die Features des MySQL Connector/Net sind:

  • Alle MySQL 5.0 Features verfügbar (Stored Procedures, etc.)
  • Alle MySQL 4.1 Features verfügbar (Server-seitige preparierte Statements, Unicode, und Shared Memory Zugriff, etc.)
  • Support für große Pakete zum Senden und Empfangen von Rows und BLOBs bis zu einer Größe von 2 GigaByte
  • Protokoll Kompression, die es ermöglicht den Datenstrom zwischen Client und Server zu komprimieren
  • Unterstützung von Verbindungen über TCP/IP Sockets, Named Pipes oder Shared Memory auf Windows
  • Unterstützung von Verbindungen über TCP/IP Sockets oder Unix Sockets
  • Unterstützung des Open-Source Frameworks Mono entwickelt von Novell
  • Vollständig verwaltet (managed), macht keinen Gebrauch von der MySQL Client Bibliothek

Einstellungen vornehmen

Bevor wir loslegen können müssen wir zunächst den MySQL Connector/NET installieren. Laden Sie sich dafür den aktuellen Treiber in Form des Installers von der offiziellen Seite herunter.

setup Download Connector/Net

Anschließend können Sie den Connector installieren.

connector_setup

Nachdem Sie den Connector erfolgreich auf Ihrem System installiert haben, können Sie Ihre Visual Studio Entwicklungsumgebung starten. Wir werden in diesem kurzen Tutorial eine kleine Windows Anwendung programmieren die sowohl Daten aus der MySQL Datenbank ausliest als auch Daten in die Datenbank schreibt.

Generieren Sie dazu ein neues C# Projekt und wählen Sie als Projekttyp eine Windows Anwendung. Bevor wir mit der MySQL Datenbank kommunizieren können, müssen wir eine entsprechende Referenz zu MySql.Data hinzufügen. Klicken Sie dazu auf die Option "Add Reference", wählen Sie die Karteikarte "Browse", suchen Sie die MySQL Komponente und fügen Sie sie dem Projekt hinzu. Sie finden die MySql.Data.dll für das .NET Framework 2.0 normalerweise im Verzeichnis "C:\Programme\MySQL\MySQL Connector Net X.X.X\bin\.NET 2.0".

add_references

Eine .NET Applikation die zu einer MySQL Datenbank verbindet

Das in diesem Tutorial vorliegende Programm basiert auf .NET 2.0 und wurde unter Visual Studio 2005 erstellt. Selbstverständlich können Sie den Quellcode auch unter .NET 3.0 oder einer aktuelleren Version nutzen. Beachten Sie aber das Sie den MySQL Connector abhängig von Ihrer Version als Referenz hinzufügen müssen! Neben den genannten Voraussetzungen ist der Zugriff auf einen laufenden MySQL Server erforderlich. Falls Sie diesen nicht haben, können Sie den aktuellen MySQL Datenbank Server samt Client kostenlos von der offiziellen Seite beziehen.

Nach den ganzen Einstellungen etc. können wir mit der Programmierung beginnen und uns direkt dem Code widmen. Die MySQL Klassen und Methoden die für uns relevant sind befinden sich im Namensraum MySql.Data.MySqlClient. Das nachfolgende Beispiel zeigt den prinzipellen Aufbau einer C# Anwendung die MySQL nutzt.

using MySql.Data.MySqlClient;
...
 
string myConnectionString = "SERVER=localhost;" +
                            "DATABASE=mydatabase;" +
                            "UID=user;" +
                            "PASSWORD=mypassword;";
 
MySqlConnection connection = new MySqlConnection(myConnectionString);
MySqlCommand command = connection.CreateCommand();
command.CommandText = "SELECT * FROM mytable";
MySqlDataReader Reader;
connection.Open();
Reader = command.ExecuteReader();
while (Reader.Read())
{
    string row = "";
    for (int i = 0; i < Reader.FieldCount; i++)
        row += Reader.GetValue(i).ToString() + ", ";
    Console.WriteLine(row);
}
connection.Close();
 
...

Die Klasse MySqlConnection repräsentiert ein Objekt welches eine Session zu einer MySQL Server Datenquelle darstellt. Der Konstruktor nimmt einen Connection String als Parameter auf, der die Zugangsdaten, wie beispielsweise den Namen und das Passwort der MySQL Datenbank beinhaltet. Über die Eigenschaft CommandText der Klasse MySqlCommand lässt sich das SQL Statement, welches ausgeführt werden soll, setzen. Die Klasse MySqlCommand repräsentiert eine SQL Anweisung (engl. Statement), die gegen die MySQL Datenbank ausgeführt werden kann.

Nachdem wir eine SQL Anweisung definiert haben, mit dem Ziel alle Reihen (engl. Rows) und Felder (engl. Fields) der Tabelle mytable auszulesen, definieren wir ein Objekt mit dem Namen Reader. Es handelt sich um ein Objekt der Klasse MySqlDataReader, welche Mittel bereitstellt um Streams von Rows zu lesen.

Nun wird die eigentliche Verbindung zur Datenbank über die MySqlConnection Methode Open() hergestellt. Mithilfe der Methode ExecuteReader() senden wir die SQL Anweisung an die Datenbank. Die Methode gibt ein MySqlDataReader Objekt zurück. Über eine einfache while() Schleife die als Argument eine Methode der Klasse MySqlDataReader nutzt, um von Reihe zu Reihe zu springen, werden die Daten nacheinander ausgelesen. Die Eigenschaft FieldCount gibt die Anzahl der Felder in der Tabellenreihe zurück. In jedem Schleifendurchgang wird die aktuelle Reihe ausgegeben.

Nachfolgend sehen Sie eine Methode zum Einfügen einer Reihe in eine MySQL Datenbank.

public void InsertRow(string myConnectionString) 
{
    // If the connection string is empty, use a default.
    if(myConnectionString == "") 
    {
        myConnectionString = "Database=Test;Data Source=localhost;
                              User Id=username;Password=pass";
    }
 
    MySqlConnection myConnection = new MySqlConnection(myConnectionString);
    string myInsertQuery = "INSERT INTO Orders (id, customerId, amount) 
                            Values(1001, 23, 30.66)";
    MySqlCommand myCommand = new MySqlCommand(myInsertQuery);
    myCommand.Connection = myConnection;
    myConnection.Open();
    myCommand.ExecuteNonQuery();
    myCommand.Connection.Close();
}

AutoSuggestBox mit MySQL und C#

Bestimmt kennen Sie die automatische Vervollständigung von Daten in Textformularen. Moderne Browser speichern beispielsweise Ihre Texteingaben ab, so dass Ihnen bei der nächsten Zeicheneingabe automatisch mögliche Vorschläge unterbreitet werden.

Mit unseren Kenntnissen lässt sich eine derartige Funktion bequem realisieren. Im nachfolgenden werden wir eine MySQL Tabellenstruktur anlegen die die Hauptstädte dieser Welt, mitsamt Länderangabe und Länderkürzel repräsentiert. Die notwendigen Daten befinden sich in einer *.sql (Structured Query Language Data) Datei, welche alle Städtedaten enthält. Unser Programm wird in der Lage sein zu einer Datenbank Verbindung aufzunehmen und bei Eingabe werden uns die entsprechenden Vorschläge angezeigt. Diese werden direkt von der MySQL Datenbank abgerufen. Nachfolgend sehen Sie das Programm wie es am Ende aussehen soll:

mysql-conn-sample-app

Die eigentlichen Daten befinden sich, wie bereits erwähnt in einer Structured Query Language Datei. Diese enthält neben den Daten selbst auch die SQL Anweisungen für die Erstellung der notwendigen Tabellen in der Datenbank. Insgesamt werden 3 Tabellen in der Applikation verwendet. Das sind tblcity, tblcountry und tblstate. Nachfolgend sehen Sie den schematischen Aufbau der Tabellen:

CREATE TABLE `tblcity` (
  `ID` int(11) NOT NULL default '0',
  `CountryID` int(11) default NULL,
  `StateID` int(11) default NULL,
  `Name` varchar(50) default NULL,
  `Code` char(3) default NULL,
  PRIMARY KEY  (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
 
CREATE TABLE `tblcountry` (
  `ID` int(11) NOT NULL default '0',
  `Code` char(2) default NULL,
  `Name` varchar(50) default NULL,
  PRIMARY KEY  (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
 
CREATE TABLE `tblstate` (
  `ID` int(11) NOT NULL default '0',
  `CountryID` int(11) default NULL,
  `Name` varchar(50) default NULL,
  `Code` char(2) default NULL,
  PRIMARY KEY  (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Die *.sql Datei befindet sich in den Projektdateien unter dem Ordner Resources und wird als Embedded Resource direkt in die Assembly einkompiliert. Das hat den Vorteil dass die Tabellenstruktur samt Daten Bestandteil des Programmes sind und nicht externe Resourcen eingebunden werden müssen. Die *.sql Datei wird bei Bedarf einfach aus der Assembly extrahiert. Beachten Sie zusätzlich die MySQL-Collation, die in unserem Beispiel dem Zeichensatz latin1 entspricht. Selbstverständlich können Sie die Tabellenstruktur nach eigenem Bedarf anpassen.

Sehen wir uns nun den Teil des Programmes an der für die Verbindung zur Datenbank verantwortlich ist.

try
{
    // Create Connection String from Input data
    string myConnectionString = "SERVER=" + maskedHost.Text + ";" + 
                                "DATABASE=" + maskedDatabase.Text + ";" +
                                "UID=" + maskedUsername.Text + ";" + 
                                "PASSWORD=" + maskedPassword.Text + ";";
 
    myConnection = new MySqlConnection(myConnectionString);
    myConnection.Open();
    if (myConnection.State == ConnectionState.Open)
        MessageBox.Show("Connection established!", "MySQL Information",
                        MessageBoxButtons.OK, MessageBoxIcon.Information);
 
    textbox_Input.Enabled = true;    
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
    MessageBox.Show(ex.Message, "MySQL Exception",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message, "Unknown Exception",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
}

Wie Sie sehen werden die Methoden in einem try{}catch{} Block gekapselt. Sie sollten den Verbindungsaufbau zur Datenbank stets in einem seperaten Exceptionblock behandeln, da insbesondere während dieses Vorgangs mit zu erwartenden kritischen Fehlern zu rechnen ist (z.B. falsches Passwort etc.). Die Methoden werfen eine entsprechende MySqlException die Sie im Verlauf Ihres Programmes abfangen können.

Nachdem eine Verbindung hergestellt wurde können die Daten ausgelesen werden. Voraussetzung dafür ist, dass die Daten tatsächlich auch in der Datenbank vorhanden sind. Falls Sie das Programm das erste Mal verwenden dürfte das noch nicht der Fall sein. Deshalb stellt das Programm einen Button namens "Create" zur Verfügung das die Anweisungen in der Embedded Resource, nämlich unserer *.sql Datei, ausführt. Der folgende Codeabschnitt aus dem EventHandler demonstriert den Vorgang.

string Commands = new EmbeddedResourceTextReader().GetFromResources
                  ("MySQLTestings.Resources.AutoSuggestBox.sql");
 
if (Commands.Length == 0)
    return;
 
MySqlCommand command = myConnection.CreateCommand();
command.CommandText = Commands;
int a = command.ExecuteNonQuery();
 
MessageBox.Show(a.ToString() + " rows were affected!", "Infobox", 
                MessageBoxButtons.OK, MessageBoxIcon.Information);

Die Klasse EmbeddedResourceTextReader implementiert eine Methode mit dem Namen GetFromResources() die den Zugriffsmodifikator internal verwendet um den Zugriff über die Assembly zuzulassen. Die Methode liefert einen string zurück der den Bytestrom der vollständigen Datei enthält. Diese wird anschließend in gewohnter Weise über ExecuteNonQuery() ausgeführt. Die Methode liefert die Anzahl der betroffenen Reihen in der Datenbank zurück. Über die MessageBox wird diese Anzahl dem Benutzer mitgeteilt. Während des gesamten Prozesses wird dem Nutzer über eine so genannte "Progress Bar" der aktuelle Stand der Operation mitgeteilt. Das Einfügen sämtlicher Daten in die Datenbank kann einige Minuten in Anspruch nehmen, da diese sequentiell mit einer kleinen Zeitverzögerung zur Datenbank geschrieben werden.

Nachdem die notwendigen Datenbankeinträge vorhanden sind kann das Programm seine Funktion ausführen und dem Benutzer, je nach Eingabe, Städte auflisten. Dazu implementiert die Textbox "Search" einen EventHandler vom Typ "TextChanged", so dass bei entsprechender Änderung auf die neuen Eingaben reagiert werden kann.

MySqlCommand command = myConnection.CreateCommand();
 
// Prevent SQL-Injection using regular expressions
// See http://www.securityfocus.com/infocus/1768 for detailed information
Regex theRegex = new Regex(@"/(\%27)|(\')|(\-\-)|(\%23)|(#)/ix",
                           RegexOptions.Compiled | RegexOptions.IgnoreCase);
 
if (theRegex.IsMatch(textbox_Input.Text) || theRegex.IsMatch(textbox_Country.Text))
{
    MessageBox.Show("Malicious Input detected! Please enter valid Data.", 
                    "MySQL Syntax Error", MessageBoxButtons.OK, 
                    MessageBoxIcon.Error);
 
    // Clear/Reset textboxes
    textbox_Input.Clear();
    textbox_Country.Text = "United States";
    return;
}
 
msCountry = (textbox_Country.Text.Length < 3) ?
            "" : "AND t2.Name = '" + textbox_Country.Text + "' ";
 
command.CommandText = "SELECT t1.Name, t1.Code, t2.Name, t3.Name " +
                      "FROM tblCity AS t1, tblCountry AS t2, tblState AS t3 " +
                      "WHERE (t1.CountryID = t2.ID)  AND " +
                      "CASE " +
                      "WHEN t1.StateID IS NULL THEN (t3.Name = 'Dummy_State') " +
                      "ELSE " +
                      "     (t1.StateID = t3.ID) " +
                      "END "
                      + msCountry +
                      "AND (t1.Name LIKE '" + textbox_Input.Text + "%') " +
                      "ORDER BY t1.Name LIMIT 10";
 
Reader = command.ExecuteReader();
 
// Remove old result
if (item1 != null)
    listView1.Items.Clear();
 
while (Reader.Read())
{
    // Create one ListViewItem and add Data
    item1 = new ListViewItem(Reader.GetValue(0).ToString(), 0);
    item1.SubItems.Add(Reader.GetValue(1).ToString());
    item1.SubItems.Add(Reader.GetValue(2).ToString());
    item1.SubItems.Add(Reader.GetValue(3).ToString());
 
    listView1.Items.AddRange(new ListViewItem[] { item1 });
}
 
Reader.Close();

Der Code beginnt mit einem zunächst einmal verwirrenden Abschnitt. Wie Sie sehen nutzen wir die .NET-Klasse Regex für Reguläre Ausdrücke.

Sobald Sie mit Datenbanken arbeiten und Abfragen von den Eingaben des Benutzers abhängig sind, besteht die Gefahr das fehlerhafte Eingaben zum Absturz bzw. zu einem undefinierten Verhalten führen. Insbesondere bei der Programmierung von Formularen für das Internet (ASP.NET) ist die Gefahr von SQL-Injektionen groß. Mit diesen ist es Angreifern möglich fremden Code einzuschleusen und somit den Ablauf Ihres Programmes zu verändern. In unserem Fall ist diese Gefahr nicht gegeben, aber bezüglich der Fehlerbehandlung und einer allgemeinen Vorsicht auf diesem Gebiet sollten Sie stets die Überprüfung der Eingabedaten in Erwägung ziehen.

Reguläre Ausdrücke (engl. regular expressions) sind gut geeignet um eingegebene Daten auf bestimmte unzulässige Muster zu überprüfen. Der in unserem Beispiel verwendete reguläre Ausdruck reicht aus um fehlerhafte/schadhafte Eingaben zu erkennen.

Nach der allgemeinen Datenüberprüfung folgt die MySQL Anweisung, die mithilfe der Benutzereingaben eine Datenbank Query ausführt. Die Anweisung liest alle Städte aus der Datenbank aus die mit den eingegebenen Buchstaben beginnen. Pro Query werden immer höchstens 10 Werte ausgelesen. Die Variable msCountry grenzt die Suche auf ein bestimmtes Land ein. Übergibt der Benutzer kein bestimmtes Land wird eine allgemeine Suche durchgeführt. Bitte bedenken Sie das die im Anhang vorhandenen Daten derzeit eine spezifische Suche nur für das Land "United States" zulassen. Sie können die Datenbankeinträge jedoch jederzeit erweitern.

Im letzten Abschnitt werden die Daten ausgelesen und in eine ListView eingetragen. Diese zeigt die Suchergebnisse im Formular an.

Schluss

Das Tutorial hat Ihnen hoffentlich einen Einblick in die Verwendung von MySQL unter C#/.NET mithilfe des MySQL Connector/Net Treibers gegeben. Sie finden auf der offiziellen Entwickler-Seite von MySQL nähere Angaben zu den Klassen und Funktionen des MySQL Connectors. Das oben gezeigte vollständige Programm mitsamt den Datensätzen für die Datenbank finden Sie im Anhang dieses Tutorials. So on, Happy Programming!

Zuletzt aktualisiert am Montag, den 23. November 2009 um 22:32 Uhr
 
AUSWAHLMENÜ