Povezivanje C# sa MySQL bazom

Započeo Marko Аcović, 31.12.2008, 14:06

prethodna tema - sledeća tema

Marko Аcović

Ovde cu ukratko objasniti kako povezati C# aplikaciju sa MySQL bazom.

Najpre je potrebno instalirati mysql connector/net, koji predstavlja interfejs izmedju mysql baze i C# aplikacije. Isti se moze skinuti sa sledece lokacije: http://dev.mysql.com/downloads/connector/net/5.2.html

Sledeci korak jeste da u svom kreiranom C# projektu dodate referencu ka MySql.Data.
Koraci za dodavanje su sledeci: Project -> Add Reference i u prozoru odaberete pomenuti konektor.

Da biste koristili ovaj konektor, na pocetku iznad definicije klase dodajte sledece:
using MySql.Data.MySqlClient;

Na kraju, mozete dodati na dogadjaj klika na dugme sledeci kod koji kupi podatke iz vase mysql baze i smesta ih u listu.
private void button1_Click(object sender, System.EventArgs e)
{
    string MyConString = "SERVER=localhost;" + "DATABASE=mydatabase;" + "UID=testuser;" + "PASSWORD=testpassword;";
    MySqlConnection connection = new MySqlConnection(MyConString);
    MySqlCommand command = connection.CreateCommand();
    MySqlDataReader Reader;
    command.CommandText = "select * from mycustomers";
    connection.Open();
    Reader = command.ExecuteReader();
    while (Reader.Read())
    {
        string thisrow = "";
        for (int i= 0; i < Reader.FieldCount; i++)
            thisrow += Reader.GetValue(i).ToString() + ",";
        listBox1.Items.Add(thisrow);
    }
    connection.Close();
}


Mislim da je kod dovoljno razumljiv da ne trebaju dodatna obajsnjenja. Ipak, ako nesto nije jasno, tu sam da razjasnimo.
Naravnom, ovaj primer podrazumeva da vec imate kreirane kontrole dugme i listbox na formi.

Toliko za ovaj put. Uzivajte u programiranju  B-)

holodoc

Odlično izgleda.

Elem... Da iskoristim ovde priliku da vidim da li ima uopšte zainteresovanih... :)

Naime... U Laboratoriji sam pre par meseci skinuo kompletan set tutorijala sa zvaničnog Microsoft-ovog sajta a u vezi ASP .NET-a, C#-a, Visual C++-a itd.

Materijala ima oko 16GB ako se dobro sećam pa ako ima zainteresovanih mogao bih lepo da ih složim i narežem na DVD diskove (3DVD-a bi bilo sasvim okej čini mi se) pa da zainteresovani studenti mogu da dalje distribuiraju taj materijal među sobom a da u laboratoriji uvek stoji jedna kopija ovih tutorijala.

Tutorijali su veoma kvalitetni inače.
<?php
abstract class Ignorance extends Stupidity implements Unavoidable 
    private function 
__construct(){
        
parent::__destruct();
    }; 

// EOF -> life.php

Marko Аcović

Stajem prvi u redu za tutorijale :)
Vec si mi letos davao neke. Ne znam da li imas jos nekih novijih :)

holodoc

E pa da. To su oni od prošle godine što si dobio kada si svraćao u Laboratoriju :) Nema ništa novo ali pretpostavljam da se broj tutorijala na zvaničnom sajtu značajno povećao a teško je zamisliti da će bilo ko van Akademske da skida materijal od petnaestak GB i više :)
<?php
abstract class Ignorance extends Stupidity implements Unavoidable 
    private function 
__construct(){
        
parent::__destruct();
    }; 

// EOF -> life.php

Nikola

Ja bih rado kopirao taj materijal. Tu bi trebalo da ima sve i svasta (bukvalno), pa ne bi bilo lose imati tako nesto.
...and justice for all

Marko Аcović

E da, zaboravih da napomenem da pomenuti kod nece da radi ukoliko nemate podignut mysql server  :).
Da aplikacija ne bi bacala exception-e, najbolje bi bilo da se taj slucaj handle-uje preko try-catch u metodi button1_Click na sledeci nacin:
try
{
    // kod za uspostavljanje konekcije i kupljenje podataka iz mysql baze
   // ...
   // ...
}
catch (MySqlException mysqlEx)
{
    MessageBox.Show("Can't connect to database!");
}

Prevodilac ce izbaciti upozorenje da je promenljiva mysqlEx deklarisana ali nikad nije koriscena. U ovom slucaju moze se zanemariti upozorenje. :)

holodoc

Citat: Nikola  31.12.2008, 15:57
Ja bih rado kopirao taj materijal. Tu bi trebalo da ima sve i svasta (bukvalno), pa ne bi bilo lose imati tako nesto.
U redu.... Videću da to posle praznika dostavim laboratoriji diskove pa ćete se vi već dogovoriti kako ćete to dalje distribuirati i razmeniti.
<?php
abstract class Ignorance extends Stupidity implements Unavoidable 
    private function 
__construct(){
        
parent::__destruct();
    }; 

// EOF -> life.php

maxogm

Citat: marko_gm  31.12.2008, 16:09
Da aplikacija ne bi bacala exception-e, najbolje bi bilo da se taj slucaj handle-uje preko try-catch u metodi button1_Click na sledeci nacin:
try
{
    // kod za uspostavljanje konekcije i kupljenje podataka iz mysql baze
   // ...
   // ...
}
catch (MySqlException mysqlEx)
{
    MessageBox.Show("Can't connect to database!");
}


Mislim da je pametno napisati i finally blok, u kome bi se vršilo zatvaranje konekcije.
try
{
    // kod za uspostavljanje konekcije i kupljenje podataka iz mysql baze
   // ...
   // ...
}
catch (MySqlException mysqlEx)
{
    MessageBox.Show("Can't connect to database!");
}
finally
{
    connection.Close();
}

holodoc

01.01.2009, 15:02 #8 Poslednja Izmena: 01.01.2009, 15:04 od holodoc
Jedno pitanje ako može... :dontknow:

Zar neće finally blok da izazove grešku (ili baci neki exception) ukoliko se metod za zatvaranje MySQL konekcije Close() pozove nad neinicijalizovanim objektom  :-SS

Hoću da kažem da pošto se finally izvršava bez obzira na to da li je bačen exception ili ne u slučaju da try blok nije bio uspešan i exception se "baci" dolazi se u situaciju da se poziva metod Close() nad nepostojećim connection objektom.

PHP bi recimo tu bacio poruku tipa E_WARNING (nekritično upozorenje) ali bi nastavio sa izvršenjem.

Pitanje za vas "oštrače C-a" :) Da li bi ovde možda u finally bloku bilo bolje da se stavi provera da li je connection inicijalizovan objekat? U PHP-u bi se recimo koristilo nešto tipa:
<?php
if(connection instanceof MySQLObjekt){
connection.Close();
}
?>

Još jednom... Još uvek nisam baš toliko bistar sa detaljima u C Sharpu pa možda grešim :) Zarad zajedničkog učenja molim da me ispravite ako grešim  b-(
<?php
abstract class Ignorance extends Stupidity implements Unavoidable 
    private function 
__construct(){
        
parent::__destruct();
    }; 

// EOF -> life.php

Marko Аcović

Moze i dva ako treba :)
Da, ako bi se ovako prosto dodao finally na kraju, prevodilac bi prijavio gresku.
Ako vec hoces da koristis finally, onda bi sledeca dva reda morao da stavis iznad try dela:

string MyConString = "SERVER=localhost;" + "DATABASE=parking;" + "UID=root;" + "PASSWORD='';";
MySqlConnection connection = new MySqlConnection(MyConString);

U ovom slucaju ti ne treba nikakva provera u finally delu.
Probao sam kod mene i radi i ovako. :) E sad ne znam da li ima mozda postoji neki slucaj da ne radi.
Ako otkrijes, javi.

holodoc

Citat: marko_gm  01.01.2009, 16:11
Moze i dva ako treba :)
Da, ako bi se ovako prosto dodao finally na kraju, prevodilac bi prijavio gresku.
Ako vec hoces da koristis finally, onda bi sledeca dva reda morao da stavis iznad try dela:

string MyConString = "SERVER=localhost;" + "DATABASE=parking;" + "UID=root;" + "PASSWORD='';";
MySqlConnection connection = new MySqlConnection(MyConString);

U ovom slucaju ti ne treba nikakva provera u finally delu.
Probao sam kod mene i radi i ovako. :) E sad ne znam da li ima mozda postoji neki slucaj da ne radi.
Ako otkrijes, javi.
Hm... Evo mojih dva centa :) Odmah da se razumemo hvatam analogiju sa PHP-om tako da opet negde možda grešim vezano za specifičnosti C# ali tu smo da učimo  <:-P

Po meni ako staviš inicijalizaciju objekta MySQL konekcije ispred try bloka onda taj blok gubi svoju funkciju jer bi neuspešna inicijalizacija po meni trebala da bude obuhvaćena proverom na "bacanje" exceptiona.

Konkretno... Šta C# vraća kao povratni tip na neinicijalizovan objekat? U PHP-u bi to bio null što je ekvivalent neinicijalizovanom objektu. E pazi sad... Zamisli da se u tom delu ispred try bloka napravi exception tj. neuspešna konekcija kao recimo posledica da je MySQL nedostupan ili isključen. Ako se u tom slučaju vrati null kao prvo mislim da će sigurno biti bačen exception pre try bloka i dobiće se "Unhandled exception" koji će sistem da uhvati najverovatnije (s obzirom da pričamo o .NET-u :)) Isto bi se verovatno desilo i da dođe do lošeg formiranja connection stringa ili bilo kog drugog razloga za neuspešnu inicijalizaciju connection objekta.

Ja bih lično stavio sve ispred try-a unutar bloka i vršio bih selektivno "bacanje" exceptiona u zavisnosti šta je pošlo naopako. Siguran sam da C# ima mnogo bolje exception handling objekte koji sadrže kod greške, output greške, trace i sl.

@Marko
Probaj da pustiš taj kod ali da isključiš MySQL server. Baš me interesuje šta će se desiti  :-SS
<?php
abstract class Ignorance extends Stupidity implements Unavoidable 
    private function 
__construct(){
        
parent::__destruct();
    }; 

// EOF -> life.php

maxogm

01.01.2009, 16:53 #11 Poslednja Izmena: 01.01.2009, 16:55 od maxo
Ništa loše neće da se desi ako je isključen mysql server... zato što se exception baca tek kod sledeće linije:
connection.Open();

a sobzorom da se ova nalazi u okviru try bloka...
Znači iskočiće ti jedan prozorčić(MessageBox.Show("Can't connect to database!"))

holodoc

Aha... Znači ovde inicijalizacija objekta tipa MySQL ne iniciira odmah i samu konekciju?

E onda je okej ako se samo konektovanje nalazi unutar try bloka a inicijalizacija objekta konekcije vani  :)

PHP koristi sličan sistem. Prvo se iniciira objekat sa neophodnim DSN-om ako se ide preko ODBC-a (a ovde pretpostavljam da se ide preko ODBC-a ili grešim?) pa se onda po potrebi otvori konekcija. Trebalo je samo da naglasite taj Open() metod u bloku  :whistle2:

Zahvaljujem na objašnjenju :)
<?php
abstract class Ignorance extends Stupidity implements Unavoidable 
    private function 
__construct(){
        
parent::__destruct();
    }; 

// EOF -> life.php

Marko Аcović

Pustao sam kod u oba slucaja i kad je ukljucen mysql server i kad nije i u oba slucaja je exception bio lepo handle-ovan, jer kao sto rece Maxo, isti se javlja tek kod linije
connection.Open();, tj. kad pokusa da otvori konekciju ka bazi.
U ovom slucaju povezivanje ide preko mysql konektora (pomenuo sam ga na pocetku), ne preko ODBC-a.