[+/-]
Häufig werden mit MySQL Binärdaten in
BLOB
-Spalten gespeichert. MySQL
unterstützt vier verschiedene BLOB-Datentypen:
TINYBLOB
, BLOB
,
MEDIUMBLOB
und LONGBLOB
.
Die Daten einer BLOB-Spalte können mit Connector/NET angesprochen und mit clientseitigem Code manipuliert werden. Es gibt keine Sonderbedingungen für den Einsatz von Connector/NET mit BLOB-Daten.
In diesem Abschnitt werden wir einfache Codebeispiele
vorstellen. Eine vollständige Musteranwendung finden Sie im
Samples
-Verzeichnis der
Connector/NET-Installation.
Um MySQL für BLOB-Daten einsetzen zu können, müssen Sie als Erstes den Server konfigurieren. Zunächst werden wir eine Tabelle anlegen. Meine Dateitabellen haben normalerweise vier Spalten: Eine AUTO_INCREMENT-Spalte passender Größe (UNSIGNED SMALLINT) dient als Primärschlüssel, um die Datei zu identifizieren, eine VARCHAR-Spalte speichert den Dateinamen, eine UNSIGNED MEDIUMINT-Spalte hält die Größe der Datei fest und eine MEDIUMBLOB-Spalte enthält die Datei selbst. Für dieses Beispiel werde ich folgende Tabellendefinition einsetzen:
CREATE TABLE file( file_id SMALLINT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, file_name VARCHAR(64) NOT NULL, file_size MEDIUMINT UNSIGNED NOT NULL, file MEDIUMBLOB NOT NULL);
Nach der Erstellung einer Tabelle muss eventuell die Systemvariable max_allowed_packet modifiziert werden, die festlegt, welche maximale Paketgröße (d. h. eine einzelne Zeile) an den MySQL Server geschickt werden kann. Nach Voreinstellung akzeptiert der Server nur 1 Mbyte als maximale Paketgröße von der Clientanwendung. Wenn Sie diesen Wert nicht überschreiten wollen, ist er in Ordnung, aber wenn doch, müssen Sie ihn heraufsetzen.
Die Option max_allowed_packet kann in den MySQL
Administrator's Startup Variables eingestellt werden. Setzen
Sie hierzu die Option Maximum allowed im Memory-Teil der
Registerkarte Networking auf einen geeigneten Wert. Dann
klicken Sie auf Apply Changes und
starten den Server über den Service
Control
-Bildschirm des MySQL Administrators neu. Sie
können diesen Wert allerdings auch direkt in der my.cnf-Datei
einstellen (und die Zeile max_allowed_packet=xxM hinzufügen)
oder die Syntax SET max_allowed_packet=xxM; in MySQL nutzen.
Bitte stellen Sie max_allowed_packet nicht zu hoch ein, da eine Übertragung von BLOB-Daten viel Zeit in Anspruch nehmen kann. Versuchen Sie, einen für Ihre Situation angemessenen Wert zu finden, und setzen Sie ihn notfalls später herauf.
Um eine Datei in eine Datenbank zu schreiben, konvertieren wir
die Datei zuerst in ein Byte-Array und übergeben dieses dann
als Parameter an die INSERT
-Anfrage.
Der folgende Code öffnet eine Datei mithilfe eines
FileStream-Objekts, liest sie in ein Byte-Array ein und fügt
sie in die Tabelle file
ein:
Visual Basic-Beispiel
Dim conn As New MySqlConnection Dim cmd As New MySqlCommand Dim SQL As String Dim FileSize As UInt32 Dim rawData() As Byte Dim fs As FileStream conn.ConnectionString = "server=127.0.0.1;" _ & "uid=root;" _ & "pwd=12345;" _ & "database=test" Try fs = New FileStream("c:\image.png", FileMode.Open, FileAccess.Read) FileSize = fs.Length rawData = New Byte(FileSize) {} fs.Read(rawData, 0, FileSize) fs.Close() conn.Open() SQL = "INSERT INTO file VALUES(NULL, ?FileName, ?FileSize, ?File)" cmd.Connection = conn cmd.CommandText = SQL cmd.Parameters.Add("?FileName", strFileName) cmd.Parameters.Add("?FileSize", FileSize) cmd.Parameters.Add("?File", rawData) cmd.ExecuteNonQuery() MessageBox.Show("File Inserted into database successfully!", _ "Success!", MessageBoxButtons.OK, MessageBoxIcon.Asterisk) conn.Close() Catch ex As Exception MessageBox.Show("There was an error: " & ex.Message, "Error", _ MessageBoxButtons.OK, MessageBoxIcon.Error) End Try
C#-Beispiel
MySql.Data.MySqlClient.MySqlConnection conn; MySql.Data.MySqlClient.MySqlCommand cmd; conn = new MySql.Data.MySqlClient.MySqlConnection(); cmd = new MySql.Data.MySqlClient.MySqlCommand(); string SQL; UInt32 FileSize; byte[] rawData; FileStream fs; conn.ConnectionString = "server=127.0.0.1;uid=root;" + "pwd=12345;database=test;"; try { fs = new FileStream(@"c:\image.png", FileMode.Open, FileAccess.Read); FileSize = fs.Length; rawData = new byte[FileSize]; fs.Read(rawData, 0, FileSize); fs.Close(); conn.Open(); SQL = "INSERT INTO file VALUES(NULL, ?FileName, ?FileSize, ?File)"; cmd.Connection = conn; cmd.CommandText = SQL; cmd.Parameters.Add("?FileName", strFileName); cmd.Parameters.Add("?FileSize", FileSize); cmd.Parameters.Add("?File", rawData); cmd.ExecuteNonQuery(); MessageBox.Show("File Inserted into database successfully!", "Success!", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); conn.Close(); } catch (MySql.Data.MySqlClient.MySqlException ex) { MessageBox.Show("Error " + ex.Number + " has occurred: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); }
Die Methode Read
des
FileStream
-Objekts lädt die Datei in ein
Byte-Array, über dessen Größe die
Length
-Eigenschaft des FileStream-Objekts
entscheidet.
Nachdem das Byte-Array als Parameter des
MySqlCommand
-Objekts zugewiesen wurde, wird
die ExecuteNonQuery
-Methode aufgerufen und
der BLOB in die file
-Tabelle eingefügt.
Sobald wir eine Datei in der file
-Tabelle
gespeichert haben, können wir sie mit der Klasse
MySqlDataReader
abrufen.
Der folgende Code ruft eine Zeile aus der Tabelle
file
ab und lädt die Daten dann in ein
FileStream
-Objekt, das auf die Festplatte
geschrieben wird:
Visual Basic-Beispiel
Dim conn As New MySqlConnection Dim cmd As New MySqlCommand Dim myData As MySqlDataReader Dim SQL As String Dim rawData() As Byte Dim FileSize As UInt32 Dim fs As FileStream conn.ConnectionString = "server=127.0.0.1;" _ & "uid=root;" _ & "pwd=12345;" _ & "database=test" SQL = "SELECT file_name, file_size, file FROM file" Try conn.Open() cmd.Connection = conn cmd.CommandText = SQL myData = cmd.ExecuteReader If Not myData.HasRows Then Throw New Exception("There are no BLOBs to save") myData.Read() FileSize = myData.GetUInt32(myData.GetOrdinal("file_size")) rawData = New Byte(FileSize) {} myData.GetBytes(myData.GetOrdinal("file"), 0, rawData, 0, FileSize) fs = New FileStream("C:\newfile.png", FileMode.OpenOrCreate, FileAccess.Write) fs.Write(rawData, 0, FileSize) fs.Close() MessageBox.Show("File successfully written to disk!", "Success!", MessageBoxButtons.OK, MessageBoxIcon.Asterisk) myData.Close() conn.Close() Catch ex As Exception MessageBox.Show("There was an error: " & ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error) End Try
C#-Beispiel
MySql.Data.MySqlClient.MySqlConnection conn; MySql.Data.MySqlClient.MySqlCommand cmd; MySql.Data.MySqlClient.MySqlDataReader myData; conn = new MySql.Data.MySqlClient.MySqlConnection(); cmd = new MySql.Data.MySqlClient.MySqlCommand(); string SQL; UInt32 FileSize; byte[] rawData; FileStream fs; conn.ConnectionString = "server=127.0.0.1;uid=root;" + "pwd=12345;database=test;"; SQL = "SELECT file_name, file_size, file FROM file"; try { conn.Open(); cmd.Connection = conn; cmd.CommandText = SQL; myData = cmd.ExecuteReader(); if (! myData.HasRows) throw new Exception("There are no BLOBs to save"); myData.Read(); FileSize = myData.GetUInt32(myData.GetOrdinal("file_size")); rawData = new byte[FileSize]; myData.GetBytes(myData.GetOrdinal("file"), 0, rawData, 0, FileSize); fs = new FileStream(@"C:\newfile.png", FileMode.OpenOrCreate, FileAccess.Write); fs.Write(rawData, 0, FileSize); fs.Close(); MessageBox.Show("File successfully written to disk!", "Success!", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); myData.Close(); conn.Close(); } catch (MySql.Data.MySqlClient.MySqlException ex) { MessageBox.Show("Error " + ex.Number + " has occurred: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); }
Nach dem Aufbau der Verbindung werden die Daten der
file
-Tabelle in ein
MySqlDataReader
-Objekt geladen. Die Methode
GetBytes
des MySqlDataReaders lädt den
BLOB in ein Byte-Array, das dann mit einem FileStream-Objekt
auf die Festplatte geschrieben wird.
Die Methode GetOrdinal
des MySqlDataReaders
kann den ganzzahligen Index einer benannten Spalte ermitteln.
Wenn Sie GetOrdinal verwenden, vermeiden Sie Fehler, die bei
einer Änderung der Spaltenreihenfolge in der
SELECT
-Anfrage entstehen könnten.
Dies ist eine Übersetzung des MySQL-Referenzhandbuchs, das sich auf dev.mysql.com befindet. Das ursprüngliche Referenzhandbuch ist auf Englisch, und diese Übersetzung ist nicht notwendigerweise so aktuell wie die englische Ausgabe. Das vorliegende deutschsprachige Handbuch behandelt MySQL bis zur Version 5.1.