[9] C# - Osnovni rad sa formom, listom i bazom podataka

[9] C# - Osnovni rad sa formom, listom i bazom podataka

offline
  • Fil  Male
  • Legendarni građanin
  • Pridružio: 11 Jun 2009
  • Poruke: 16586

[0] Uvod




* Za 9000. poruku, tradicionalno --> poklon čitaocima novi članak Smile



Do sada je u članku forsirano okruženje MonoDevelop, na operativnom sistemu Linux. U ovome članku će biti obrađen rad sa razvojnim okruženjem Visual Studio, na operativnom sistemu Windows.

Arrow Preuzmite: Visual Studio 2012 Express for Windows Desktop
* express verzija je besplatna i radiće bez regsitracije 30 dana; registracijom, dobijamo besplatan ključ (serijski broj) za softver.

Idea Takođe, u članku će biti rađeno sa Microsoft Access 2007 bazom podataka (ekstenzija: accdb)


Ideja članka je da čitaoca motiviše da istražuje i da, koristeći uputstva za ovaj članak i prethodne članke, unapredi kod, doradi ga i pokuša da napravi sopstvenu bazu podataka.
Ponegde u članku će biti napisan "nagoveštaj" (hint), šta se može pokušati, a ako članak bude popularan, članak će biti proširen i sa drugim konceptima (npr. kreiranje niti koje brišu unose iz baze, po nekom kriterijumu i drugo).

Exclamation Zadatak je sledeći: treba napraviti Windows aplikaciju koja će u bazu podataka unositi određene podatke, vezane za nekog forumaša na MyCity-ju. Ti podaci neka budu: broj forumaša, njegovo ime, prezime, nadimak (nick) i informacija da li je korisnik vidljiv ili sakriven na forumu.
Za korisnike u bazi treba omogućiti tabelarni prikaz korisnika i preko liste implementirati navigaciju za unose u bazi: prikaz prvog i poslednjeg korisnika u bazi, kao i prethodnog i sledećeg korisnika u bazi.

* Napomena: postoje različiti pristupi komuniciranja sa bazom podataka, i lakši i teži od ovde opisanog (recimo kroz kontrole na formi, zatim upotrebe drugih klasa i sl.). Ovo je samo jedna od različitih mogućnosti.





[1] Kreiranje projekta i dizajn forme




- Pokrenimo alat Visual Studio i kreirajmo novi projekat: File --> New Project....
- Odaberite opcije sa sledeće slike i kliknite na dugme OK:



Slika 1: Kreiranje Windows Forms aplikacija


Dočekaće vas prazna forma. Odabrao sam da najpre uradimo dizajn forme, jer dizajn nije mnogo bio u fokusu u prethodnim člancima, a i ja kada pročitam neki zahtev, pokušavam da zamislim u glavi kako bi mogla da izgleda forma te aplikacije. Dakle, od značaja nam je panel Toolbox (pregledajte listu panela u meniju View. Ako slučajno isključite neki toolbar ili panel, ovaj meni je mesto gde ga možete opet aktivirati). Proučite malo ovaj panel i vidite kakvih sve komponenti ima u njemu.



Slika 2: prikaz najčešćih kontrola u panelu Toolbox


Kontrole (komponente) se dodaju na formu dvostrukim klikom ili prevlačenjem kontrole na formu. Takođe, ako je potrebno više identičnih kontrola na formi, one se mogu brzo kopirati (CTRL + C, CTRL + V).

Ja sam zamislio da forma izgleda ovako:



Slika 3: prikaz jedne od mogućih solucija za dizajn forme


Dakle, dodajmo kontrole na formu i podesimo njihove osobine (eng. properties):



Slika 4: prikaz promene osobina labele na formi


Kroz panel Properties menjamo osobine kontrola, na primer: ime kontrola, tekst koji kontrola ispisuje, vidljivost kontrole i druge. Za stanje kao na slici 3, trebaće nam sledeće kontrole:
- 5 labela (Label)
- 4 polja za unos teksta (TextBox)
- 1 padajuća lista (ComboBox)
- 1 kontrola koja može imati tabelarni prikaz (DataGridView)
- 6 dugmadi (Button)

Rasporedite kontrole i izmenite im osobine tako da odgovaraju stanju na slici 3; ja sam ovako podesio osobine kontrola na formi:


Arrow + Labele:

Arrow + Polja za unos teksta:

Arrow + Padajuća lista:

Arrow + Grid:

Arrow + Dugmad





[2] Dodavanje novih klasa i definisanje klase Forumas




- Dodaćemo novu klasu u projekat: unutar panela Solution Explorer, kliknite desnim tasterom miša na ime projekta, birajte stavku Add i odaberite stavku Class.... Dajte joj ime "Forumas".



Slika 5: dodavanje nove klase u projekat




Slika 6: odabir i imenovanje klase


Kada "uđemo" u klasu, primetićemo da su već definisane neke "using" linije, namespace i definicija klase Forumas.

U ovoj klasi ćemo definisati privatna polja i odgovarajuće Property polja ("setere" i "getere"), preko kojih se može čitati i/ili pisati u neko polje (tj. promenljivu).

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Forumasi {     class Forumas     {         private int brojForumasa;         public int BrojForumasa         {             get { return brojForumasa; }             set { brojForumasa = value; }         }                 private string ime;         public string Ime         {             get { return ime; }             set { ime = value; }         }                 private string prezime;         public string Prezime         {             get { return prezime; }             set { prezime = value; }         }                 private string nick;         public string Nick         {             get { return nick; }             set { nick = value; }         }                 private string vidljivost;         public string Vidljivost         {             get { return vidljivost; }             set { vidljivost = value; }         }                 public Forumas()         {             //parametherless konstruktor         }                 public Forumas(int brFor, string ime, string prez, string nick, string vidljivost)         {             brojForumasa = brFor;             this.ime = ime;             prezime = prez;             this.nick = nick;             this.vidljivost = vidljivost;         }     } }


Idea Lak način da kreirate polja i njegove settere i gettere je da ukucate propfull i dva puta pritisnete taster TAB. Rezultat ove akcije je sledeće parče koda koje se generiše automatski (code snippet):

private int myVar;    public int MyProperty    {       get { return myVar;}       set { myVar = value;}    }

Na ovaj način ćete brzo da "završite" klasu i njene konstruktore.
Napomena: ukoliko se desi da se podudari ime polja klase sa imenom parametra u konstruktoru, mora se koristiti ključna reč this. Vidite kod. Ključna reč this ukazuje na to da se radi o elementu klase, a ne konstruktora. Dakle: this.ime=ime; označava da se polju klase s nazivom ime, dodeljuje vrednost parametra ime iz konstruktora.





[3] Kreiranje baze podataka




OK, pošto je prošao šablonski deo, da se opet vratimo na zanimljive stvari. smešak

- Pokrenite Access i kreirajte New Blank Database.

- Desnim tasterom miša kliknite na "Table1" i odaberite Design View. Kada se otvori polje za unos imena, unesite: "TForumas".

- Unesite podatke kao na sledećoj slici:



Slika 7: kreiranje strukture tabele u Design View-u


Polja su, dakle: "BrojForumasa", "ImeForumasa", "PrezimeForumasa", "NickForumasa", "VidljivostForumasa".

BrojForumasa treba definisati kao primarni ključ (videti opciju sa ribbona: Primary Key)
Primarni ključ jednoznačno identifikuje zapis u bazi. Broj forumaša, dakle, jednoznačno identifikuje nekog forumaša i ne može se desiti da postoje dva člana foruma koji se vode pod istim brojem.

Idea Ja sam sačuvao bazu unutar: C:\

Ovi unosi iz Design View-a će se transponovati u kolone unutar Datasheet View-a.
Inače, eksperimentište sa osobinama ovih unosa. Na primer, dozvoljena veličina stringa, ili kod primarnog ključa uočite da je definisano da nema duplikata.

Izgled baze kada sam završio aplikaciju i preko nje uneo par forumaša:



Slika 8: Pregled unosa tabele u Datasheet View-u





[4] Kreiranje klase Broker




Klasa Broker je usko vezana za bazu podataka; u njoj će se manipulisati konekcijama, transakcijama, zadavaće se SQL upiti i drugo.

Najpre, kreirajmo klasu Broker (videti sliku 5 i sliku 6).

Exclamation U tekstu će biti objašnjeni delovi koda, a na kraju objašnjenja će, unutar spoilera, biti dodat čitav kod.

- Najpre, neophodno je dodati par using direktiva, prvenstveno:
Citat:using System.Data;
using System.Data.OleDb;



- Dalje, deklarisaće se sledeće promenljive: komanda, konekcija i transakcija i definisati konekcioni string:
OleDbCommand command; OleDbConnection connection; OleDbTransaction transaction; private string connectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Forumasi.accdb; Persist Security Info=False;";

Uočimo specifičnu sintaksu konekcionog stringa. Izgled konekcionog stringa zavisi od više faktora, na primer tip baze (Access, SQL Server, MySQL...) i drugih parametara (zaštita i drugo).

Primer konekcionog stringa koji sam koristio u Visual Studio 2005 za staru Access-ovu bazu (format 2000, ekstenzija mdb):
private string connectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\NekaBaza.mdb;";


Arrow Koristan link za konekcione stringove: ConnectionStrings
* odaberite sa kojom bazom radite i vidite primere konekcionih stringova
* Još jedan primer, sa foruma MyCity: LINK

- Unutar konstruktora klase broker izvršimo inicijalizaciju konekcije, na osnovu konekcionog stringa:

public Broker()         {             connection = new OleDbConnection(connectionString);         }


- Transakcija se može shvatiti kao logičko izvršenje jedne jedinice posla. Transakciju započinjemo kada treba da uradimo neke aktivnosti nad bazom i to kada je otvorena konekcija na bazu:

public void PocniTransakciju()         {             try             {                 if (connection.State != ConnectionState.Open)                     connection.Open();                 transaction = connection.BeginTransaction();             }             catch (Exception ex) { MessageBox.Show("Doslo je do greske prilikom pocinjanja transakcije" + ex); }         }

Transakcije se odvijaju po principu "sve ili ništa", i postoje izvesne osobine transakcije (ACID). Saznajte više o transakcijama: LINK.


- Sledeći kod će ubaciti objekat klase Forumas u bazu:

public void InsertForumas(Forumas fr)         {             PocniTransakciju();             command = new OleDbCommand();             string upit = "INSERT INTO TForumas VALUES('" + fr.BrojForumasa + "','" + fr.Ime + "','" + fr.Prezime + "','" + fr.Nick + "','" + fr.Vidljivost + "')";             try             {                 command.CommandText = upit;                 command.Connection = connection;                 command.Transaction = transaction;                 command.ExecuteNonQuery();                 transaction.Commit();             }             catch (Exception ex)             {                 transaction.Rollback();                 throw new Exception("Broker.InsertForumas", ex);             }             finally { connection.Close(); }         }

Dakle, nakon što započnemo transakciju, zadaje se SQL komanda koju treba izvršiti nad bazom. Za potrebe ovog primera, neophodno je znati osnove SQL jezika (vidi LINK). Određenoj komandi, dakle, dodeljujemo konkretan upit, konekciju i transakciju, nakon čega je izvršavamo.

Dobra praksa je koristiti try-catch-finally blokove baš po ovoj šemi:
- unutar try bloka definišemo gde ima "prostora za grešku", uključujući i Commit transakcije. Ako dođe do greške, unutar catch bloka poništavamo transakciju sa rollback, dok u finally bloku (koji se svakako izvršava) zatvaramo konekciju. Izuzeci su objašnjeni u jednom od prethodni članaka, pa ako ovaj deo nije jasan, preporučujem da se taj članak pročita.


- Select SQL upit koji vadi sve zapise iz baze je obrađen u sledećem kodu:

public DataTable SelectForumas()         {             PocniTransakciju();             command = new OleDbCommand();             try             {                 command.CommandText = "SELECT * FROM TForumas";                 command.Connection = connection;                 command.Transaction = transaction;                 DataTable forumasi = new DataTable();                 OleDbDataAdapter adapter = new OleDbDataAdapter(command);                 adapter.Fill(forumasi);                 transaction.Commit();                 return forumasi;             }             catch (Exception ex)             {                 transaction.Rollback();                 throw new Exception("Broker.SelectForumas", ex);             }             finally { connection.Close(); }         }     } }
Kao što se vidi, i ovaj upit je jednostavan. Inače, ovi upiti su osnovni i jednostavni.
Idea Za domaći, probajte da napišete DELETE upit. U kasnijem proširenju članka će i on biti objašnjen.

Elem, ovde umnogome olakšava posao objekat klase DataAdapter, koji je sposoban da na osnovu prosleđenog upita popuni DataTable (koji je i izlaz iz funkcije).


Arrow + Vidi kompletan kod





[5] Upotreba generičkih listi i obrada događaja dugmadi




Za početak, otvorite formu koju ste dizajnirali i dvostrukim klikom overite svu dugmad na formi. Dvostrukim klikom na neko dugme ćemo automatski formirati deo koda koji obrađuje događaj "On Click".

Na primer, dvostrukim klikom na dugme "Prikazi", kreiraće se ovaj deo koda:

private void btnPrikazi_Click(object sender, EventArgs e)         {           // neki_blok_koda         }

Dakle, svaki put kada kliknemo na dugme "Prikazi", izvršiće se neki_blok_koda (deo koda koji definišemo).

Vratimo se na početak klase naše forme (ja joj promenih ime u MyCity) i unesimo ispod definicije klase sledeće:

Broker broker = null; List<Forumas> lista = null; int tekuciIndex = 0;

List<Forumas> je generička lista, dakle, lista koja se sastoji od specifičnih objekata (forumasa). Za upotrebu generičkih listi, neophodna je using direktiva: using System.Collections.Generic;

tekuciIndex će nam služiti kao pokazivač na neki element u generičkoj listi.

Unutar konstruktora forme se dodeljuju vrednosti brokeru, listi i vrši se inicijalizacija komponenti forme.


Zbog preglednosti koda, mogu se koristiti tzv. regioni. U kodu se može videti da sam definisao dva regiona:



Slika 9: Upotreba regiona radi preglednosti koda


Klikom na plusić, "razvija se" deo koda vezan za definisani region. Region se formira na sledeći način:

Citat:#region Ime regiona
#endregion


Prvi region je vezan za listu: + VIDI KOD

Metoda TransformisiUListu uzima objekat tipa DataTable i transformiše u listu forumaša. Ovde nema mnogo mudrosti: treba izvrtiti petlju tako da se na osnovu svakog reda izvuku podaci i napravi forumaš - koga ćemo ubaciti u listu u svakoj iteraciji.

Metoda PrikaziForumasaNaPoziciji je zadužena da na osnovu zadatog indeksa, zaviri na tu poziciju u generičkoj listi i da, na osnovu konkretnog forumaša u listi - popuni Text Boxove i Combo Box na formi.

Metoda PostojiForumasUListi je zamišljena da se koristi u svrhu zaštitnog mehanizma, dakle, da nije moguće uneti dva forumaša koji bi imali isti brojForumasa.
Idea Ovaj mehanizam se zasniva na proveri iz liste! Petlja izvrti da li je broj nađen u listi --> za domaći: osmisliti metodu koja će čitati vrednosti iz baze kako bi videla da li ima te vrednosti u bazi (može biti objašnjeno u ekstenziji članka).


Drugi region je vezan za dugmad.

btnUnesi_Click - treba da proveri (na neki način, a ovde čitamo iz liste) da li već ima forumaša sa konkretnim brojem i ako nema, napravi objekat forumaša na osnovu podataka iz forme, i najzad, da "kaže" brokeru da ga ubaci u bazu.

btnPrikazi_Click - služi za punjenje grida, njegovo osvežavanje (da se prikažu ažurni podaci), i transformaciju ovih podataka u listu.

Ostali dugmići su navigacioni i barataju sa indeksom i prikazuju određenog forumaša u zavisnosti od pozicije u listi (određene na osnovu tog indeksa).

Arrow + Vidi kompletan kod klase



Do sledećeg članka Ziveli

E, da Mr. Green I kome zatreba ( Mr. Green ) , evo ga gotov solution sa bazom smešak


[url=https://www.mycity.rs/must-login.png



Registruj se da bi učestvovao u diskusiji. Registrovanim korisnicima se NE prikazuju reklame unutar poruka.
offline
  • Dario V.
  • Pridružio: 10 Jan 2012
  • Poruke: 975

e druze svaka tebi cast, ovaj kurs si poceo 1 Novembra 2011. u 00:14, odnosno tada je objavljen prvi clanak, a sto je najbolje traje i dalje, samo guraj.

Svaka tebi jos jednom cast, samo tako nastavi, mnogi ovo prate i uce se !

Pozdrav!



offline
  • Milan
  • Pridružio: 17 Dec 2007
  • Poruke: 14809
  • Gde živiš: Niš

Jel može neko da mi objasni gde grešim?



dgvGrid1 se kreira u f-ji InitializeComponent(), ali mi neposredno posle toga dibager javlja da ne postoji instanca tog objekta. Kada istu f-ju pozovem nad istim objektom nešto kasnije u programu sve lepo radi.

Ko je trenutno na forumu
 

Ukupno su 1065 korisnika na forumu :: 38 registrovanih, 9 sakrivenih i 1018 gosta   ::   [ Administrator ] [ Supermoderator ] [ Moderator ] :: Detaljnije

Najviše korisnika na forumu ikad bilo je 3466 - dana 01 Jun 2021 17:07

Korisnici koji su trenutno na forumu:
Korisnici trenutno na forumu: 357magnum, AF-1, airsuba, amaterSRB, bojank, Chainsaw, comi_pfc, Dimitrise93, Dorcolac, draganca, draganl, HogarStrashni, hooraay, Ilija Cvorovic, Karla, Kvazar, ladro, Luka Blažević, Milometer, milos.cbr, Milos82, MilosKop, mocnijogurt, nemkea71, novator, Panter, Parker, pein, procesor, sasa87, Shinobi, Sirius, Smd, Srle993, stegonosa, vathra, VP6919, |_MeD_|