Cezary Błaszczyk 15.03.2008 Obsługa MySQL w C# Wstęp Aby móc napisać i uruchomić aplikacje oparte o język C# obsługujące MySQL, potrzebna jest platforma .NET, kompilator języka C# oraz odpowiedni sterownik obsługujący bazę danych MySQL. Platforma .NET Platforma .NET Framework – jest to platforma programistyczna działająca tylko na systemach operacyjnych rodziny Windows, ale również istnieją niezależne wdrożenia .NET takie jak Mono.Net, dotGNU działające również pod Linux, Mac OS X, UNIX. W skład platformy .NET wchodzi środowisko uruchomieniowe Common Language Runtime (CLR) oraz biblioteki klas (Base Class Library – BCL). CLR służy do kompilacji oraz wykonania pośredniego kodu aplikacji Common Intermediate Language (CIL). Biblioteki klas BCL to zestaw klas, interfejsów oraz funkcji umożliwiające współpracę aplikacji z systemem operacyjnym. Dzięki temu aplikacje nie są zależne od systemu operacyjnego. Język C# Jest to obiektowy język programowania. Należy do rodziny języków C/C++, dlatego nie trudno znaleźć podobieństwo C# do języków C++, Java. Aplikacje napisane w języku C# są kompilowane do pośredniego kodu czyli do języka CIL wykonywanego później w środowisku uruchomieniowych CLR platformy .NET. Co to jest ADO.NET? ADO.NET wchodzi w skład platformy .NET (jest częścią BCL). ADO.NET jest to zbiór klas umożliwiających współprace z danymi takimi jak różnego typu relacyjne bazy danych (np. MySQL, Oracle, SQL Server), pliki XML, pliki Microsoft Excel, pliki tekstowe. Aby móc łączyć się z bazą danych potrzebny jest interfejs dostępowy do konkretnego typu bazy danych. W języku C# do komunikacji z MySQL możemy użyć trzech sposobów: poprzez interfejs OLE DB, interfejs ODBC oraz sterownik zewnętrzny. Interfejs ODBC ODBC (ang. Open DataBase Connectivity - otwarte łącze baz danych) - interfejs pozwalający programom łączyć się z systemami zarządzającymi bazami danych. Jest to API niezależne od języka programowania, systemu operacyjnego i bazy danych. W skład ODBC wchodzą wywołania wbudowane w aplikacje oraz sterowniki ODBC.1 Zalety: • Niezależność od systemu operacyjnego • Niezależność od języka programowania • Niezależność od typu bazy danych • Bardzo łatwe i szybkie przejście z jednej bazy na inną Wady: • Szybkość odczytu danych • Szybkość inicjacji obiektów • Niepełna implementacja MySQL Interfejs OLE DB OLE DB (ang. Object Linking and Embedding, Database) - interfejs programistyczny firmy Microsoft służący do uzyskiwania dostępu do danych. Jest to obiekt COM, który funkcjonuje w podobny sposób jak ODBC, ale w odniesieniu do dowolnego źródła danych, a nie tylko baz danych SQL.2 Zalety: • Bardzo łatwe i szybkie przejście z jednej bazy na inną • Szybkość zapisu, modyfikacji, usuwania danych Wady: • Działa tylko na aplikacjach zrobionych pod rodzinę systemów operacyjnych Microsoftu 1 2 Źródło http://pl.wikipedia.org/wiki/ODBC Źródło http://pl.wikipedia.org/wiki/OLE_DB • Działa tylko w wybranych przez Microsoft językach programowania • Szybkość odczytu danych • Niepełna implementacja MySQL • Szybkość inicjacji obiektów Sterownik zewnętrzny Są to sterowniki pisane tylko i wyłącznie do obsługi baz danych MySQL. Zalety: • Szybkość odczytu danych • Zazwyczaj niezależność od systemu operacyjnego (wyjątkiem jest sterownik MyDirect.NET) • Zazwyczaj niezależność od kompilatora (wyjątkiem jest sterownik MyDirect.NET) • Szybkość zapisu, modyfikacji, usuwania danych • Pełna implementacja MySQL Wady: • Działają tylko z bazą danych MySQL • Są zależne od wersji MySQL (podczas wejścia nowej wersji bazy danych może być potrzebne również zainstalowanie nowszej wersji sterownika) • Szybkość odczytu danych w wypadku sterownika MySQLDriverCS Obiekty ADO.NET wykorzystywane w operacjach na bazach danych Do głównych typów obiektów tej biblioteki wykorzystywanych do łączenia się z bazą należą Command, Connection, DataAdapter, DataReader oraz obiekt DataSet. Napisałem typów obiektów, a nie obiektów ponieważ dla każdego sposobu łączenia się są to inne obiekty (klasy), ale posiadające bardzo zbliżoną funkcjonalność jak i nazewnictwo. Tabela 1 Nazwy obiektów dla poszczególnych sposobów łączenia się z bazą danych MySQL Typ obiektu Nazwa w ODBC Nazwa w OLE DB DataReader OdbcDataReader OleDbDataReader Connection OdbcConnection OleDbConnection Command OdbcCommand OleDbCommand DataAdapter OdbcDataAdapter OleDbDataAdapter Nazwa w sterownikach zewnętrznych3 MySQLDataReader MySqlDataReader MySQLConnection MySqlConnection MySQLCommand MySqlCommand MySQLDataAdapter MySqlDataAdapter Connection Connection – jest to typ obiektu służący do komunikacji z bazą danych. Wszystkie obiekty typu Connection posiadają właściwości umożliwiające ustawianie oraz modyfikowanie parametrów połączenia. Poprzez komunikację z bazą danych należy mieć na myśli rozpoczęcie i zakończenie połączenia oraz stworzenie poleceń SQL. Obiekt tego typu posiada również obsługę transakcji. Obiekt można tworzyć i nadać parametry poprzez dwa sposoby: • Inicjacje obiektu poprzez pusty konstruktor i poprzez pole ConnectionString podanie parametrów • Inicjacje obiektu poprzez pusty konstruktor, w którym podajemy parametry połączenia Tabela 2 Łańcuch znaków wskazujący parametry połączenia dla poszczególnych sposobów: Sposób łączenia się z bazą ODBC OLE DB Sterownik zewnętrzny 3 Łańcuch znaków zawierający parametry DRIVER={MySQL ODBC 5.1Driver}; UID=uzytkownik; PWD=haslo123; Database=baza; Server=localhost Provider=OleMySql.MySqlSource.1; Data Source=localhost,3306; Initial Catalog=baza; User ID=uzytkownik; Password=haslo123 Server=localhost;Database=baza;User ID=uzytkownik; Password=haslo123; Pierwsza nazwa jest dla sterownika MySQLDriverCS, druga zaś dla MySQL Connector /NET, MyDirect .NET oraz ByteFX.Data Command Typ obiektu Command służy do wykonania poleceń SQL oraz pobranie powstałych wyników. Aby stworzyć obiekt typu Command i połączyć go z obiektem typu Connection można użyć czterech sposobów: • Inicjacje obiektu poprzez pusty konstruktor i następnie poprzez pole Connection powiązać obiekt Command z obiektem Connection. • Inicjacje obiektu poprzez konstruktor, w którym podajemy składnię polecenia SQL • Inicjacje obiektu poprzez konstruktor, w którym podajemy składnię polecenia SQL oraz obiekt Connection • Poprzez użycie metody CreateCommand() z obiektu Connection. Aby uruchomić polecenie SQL i pobrać jej wynik używamy jednej z trzech metod: • ExecuteReader() – zwracanym wynikiem jest obiekt typu DataReader, tej metody używa się dla poleceń SELECT • ExecuteScalar() – zwracanym wynikiem jest obiekt typu Object, tej metody używa się dla poleceń SELECT, dla których wynikiem jest tylko jedno pole (jeden jednokolumnowy rekord) • ExecuteNonQuery() – zwracanym wynikiem jest zmienna int informująca ile rekordów zostało zmienionych, dodanych lub usuniętych. Tej metody używa się dla aktualizacji, dodawania lub usuwania rekordów. DataAdapter Obiekty DataAdapter pośredniczą w wymianie danych pomiędzy obiektem DataSet a źródłem danych. Wykorzystywany jest do uruchomienia wypełnienia obiektu DataSet wynikiem uruchomionego polecenia SELECT poprzez metodę Fill. Kolejną funkcją DataAdapter jest wprowadzenie zmian danych w obiekcie DataSet z powrotem do bazy danych. Wykonuje się to poprzez metodę Update. Polecenia SQL(INSERT, UPDATE, DELETE) mogą być tworzone automatycznie przez typ obiektu DataAdapter, ale również jest możliwość stworzenia własnego polecenia dla obiektu typu Command i dowiązanie go do DataAdapter poprzez pole: • InsertCommand – dla polecenia INSERT • UpdateCommand – dla polecenia UPDATE • DeleteCommand – dla polecenia DELETE DataReader Obiekty typu DataReader służą do pobrania z bazy danych strumieni danych tylko do odczytu. Dane są zapisane w buforze klienta i przechowywane tam do czasu wykonania metody Read(). Każde uruchomienie metody Read() zwraca wartość logiczną bool informująca czy został jakiś rekord do odczytu, jeśli wynikiem będzie true można z obiektu DataReader pobrać jeden rekord w postaci obiektów Object (jest ich tyle ile kolumn zostało zwróconych w wyniku). Jest to najszybsza możliwość pobrania wyników wykonanych poleceń, jak i najmniej obciążająca zasoby systemu ( W pamięci znajduje się tylko jeden rekord). Obiekt powstaje poprzez wykonanie metody ExecuteReader() obiektu Command. Po odczytaniu wszystkich rekordów należy wykonać metodę Close() zamykającą obiekt typu DataReader. DataSet DataSet jest obiektem służącym do przechowywania danych z baz danych. Obiekt DataSet jest umieszczany w pamięci. Swą budową przypominają relacyjną bazy danych, tzn. zawierają kolekcje tabel, kolumn, wierszy i zdefiniowanych relacji.4 Dzięki temu praca na obiekcie DataSet jest bardzo podobna jak praca na bazie danych. Gdy dane poprzez DataAdapter zostaną wprowadzone do DataSet to można rozłączyć połączenie z bazą i pracować na tych danych w trybie offline. Wszystkie dane, które zostaną zmienione, dodane bądź usunięte można później zmodyfikować w bazie danych podczas utworzenia kolejnego połączenia. Jest to możliwe tylko wtedy, gdy w każdej tabeli znajdującej się w obiekcie DataSet dane będą miały klucz główny. Jako, że po jakimś czasie dane w bazie danych może ktoś zmienić, dzięki obiektowi DataAdapter można zaktualizować zmienione rekordy w obiekcie DataSet, a nie pobierać wszystkie dane ponownie. Etapy łączenia się z bazą danych. Łączenie z bazą danych w ADO.NET można podzielić na 3 etapy: 1. Otwarcie połączenia z bazą danych. 4 Źródło http://pl.wikipedia.org/wiki/DataSet 2. Wykonania serii operacji na bazie danych oraz odczytanie ich wyników. Wyniki można zapisać do podstawowych obiektów lub zmiennych języka C# za pomocą typu obiektu DataReader albo wypełnienie obiektu DataSet. 3. Zamknięcie połączenia. Jako, że wyniki operacji na bazie danych są zapisywane do obiektów lub zmiennych języka C#, nie ma konieczności utrzymywania połączenia, w celu dalszego wykorzystywania danych. Otwarcie połączenia z bazą danych. Do otwarcia połączenia z bazą danych służy typ obiektu Connection. Najpierw należy w obiekcie typu Connection podać parametry łączenia z bazą danych. Następnym krokiem jest wywołanie metody Open(). Wykonanie operacji na bazie danych. Po połączeniu się z bazą danych należy stworzyć polecenie operacji na bazie danych za pomocą typu obiektu Command. Najwygodniejszym sposobem utworzenia takiego typu obiektu jest poprzez wykorzystanie metody CreateCommand z typu obiektu Connection, a następnie za pomocą pola CommandText typu obiektu Command. Sposób wykonania operacji na bazie danych i odczytu wyników operacji zależy od typu obiektu jaki ma zostać wypełniony. Dla obiektu DataSet należy stworzyć typ obiektu DataAdapter, dowiązać do niego typ obiektu Command oraz użyć metody Fill lub Update. Dla typu obiektu DataReader, obiektu Object i zmiennej int wywołujemy odpowiednią metodę typu obiektu Command. Zamknięcie połączenia. Aby zamknąć połączenie z bazą danych należy w typie obiektu Connection użyć metody Close(). Prosty przykład dla sterownika zewnętrznego MySQL Connector /NET Jest to przykład odczytu danych z jednej tabeli. Kod programu dla innych sposobów łączenia się z bazą MySQL jest bardzo podobny. Pierwszą zmianą są zmiany obiektów MySqlCommand, MySqlDataReader, MySqlConnection, na ich odpowiedniki zgodnie z tabela nr 1.Drugą zmianą jest zmiana łańcucha znaków zgodnie z tabelą nr 2. namespace connectornet_polaczenie{ public class polaczenie_connectornet { MySqlCommand dbcmd; MySqlDataReader dbreader; MySqlConnection con; string wynik_string, zapytanie; public polaczenie_connectornet(){} public string wyswietlenie() { con = new MySqlConnection(); con.ConnectionString = "Server=localhost;Database=bazaUser ID=uzytkownik;Password=haslo123;"; try{ con.Open(); dbcmd = con.CreateCommand(); zapytanie = "SELECT * FROM tabela1"; dbcmd.CommandText = zapytanie; dbreader = dbcmd.ExecuteReader(); if (dbreader.Read()) { do{ wynik_string = ((int)dbreader["id1"]).ToString() + (string)dbreader[1] + (string)dbreader[2]; } while (dbreader.Read()); } else { wynik_string = "nic"; } dbreader.Close(); dbreader = null; dbcmd.Dispose(); dbcmd = null; con.Close(); }catch (Exception ex){Console.WriteLine(ex.ToString());} return wynik_string; }}