lab_2_5_dataset
DESCRIPTION
distribucijaTRANSCRIPT
Laboratorijske vježbe 2.5 Pristup bazi podataka korištenjem DataSet-ova
Sažetak
U ovim vježbama proći ćemo kroz gotovo najstariji način korištenja baze podataka koju
podržava .NET, odnosno korištenjem DataSet-ova. Uz same DataSet-ove proći ćemo kratko i
kroz SQL Server 2012. Pročiti ćemo pohranjene procedure, okidače (engl. trigger) i vezanje
podataka sa kontrolama (engl. data binding)
Ključne riječi: ADO.NET, DataSet, SQL Server 2012
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
© 2013, University of Zagreb, Faculty of Organization and Informatics, Varaždin 2
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
Sadržaj
1. Uvod ....................................................................................................................................................................................... 2
2. SQL Server 2012 ................................................................................................................................................................ 2
2.1. Kreiranje baze podataka i tablica ......................................................................................................................... 3
2.2. Postavljanje upita ....................................................................................................................................................... 4
2.3. Pohranjene procedure i okidači............................................................................................................................ 4
2.4. Okidač ............................................................................................................................................................................. 5
2.5. Detach / Attach database ....................................................................................................................................... 6
2.6. Northwind baza podataka ...................................................................................................................................... 6
3. Pristupanje bazi podataka korištenjem DataSet-ova. ........................................................................................ 7
3.1. Kreiranje nove aplikacije sa pristupom podacima ........................................................................................ 8
3.2. Spajanje na bazu podataka .................................................................................................................................... 9
3.3. Prikaz podataka – READ ....................................................................................................................................... 10
3.4. Brisanje podataka - Delete .................................................................................................................................. 15
3.5. Dodavanje novih redaka – Create ..................................................................................................................... 16
3.6. Dodavanje stavki ..................................................................................................................................................... 19
3.7. Ažuriranje zapisa - Update .................................................................................................................................. 22
4. Pitanja za ponavljanje .................................................................................................................................................. 25
5. Literatura (pristupano u periodu ljetnog semestra ak.g. 2012/2013) ....................................................... 25
1. Uvod U ovim materijalima koristi ćemo sustav za upravljanje bazom podataka, kako bismo kreirali
bazu podatka i isprobali dohvaćanje, pohranu, ažuriranje i brisanje podataka (CRUD), a nakon
toga ćemo napraviti jednu aplikaciju koja samostalno pristupa podacima i omogućuje CRUD
operacije.
2. SQL Server 2012 Microsoft SQL Server je sustav za upravljanje relacijskom bazom podataka. Iako postoji više
definicija baze podataka, mi ćemo koristiti najjednostavniju prema kojoj je baza podataka
(kolokvijalno nazivana samo baza) organizirani skup podataka. Organiziran u ovom slučaju
znači da postoje stroga formalno definirana pravila koja se primjenjuju za pohranu podataka.
Sustav za upravljanje bazom podataka omogućuje kreiranje, čitanje, ažuriranje i brisanje baza
podataka, dok baza podataka sadrži tablice, koje su preslika relacijskog modela podataka i u
© 2013, University of Zagreb, Faculty of Organization and Informatics, Varaždin 3
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
Slika 1: Kreiranje strukture tablice
njima pohranjuje strukturirane zapise. Uz Microsoft SQL Server 2012 kojeg ćemo koristiti na
ovom kolegiju, postoji još mnogo drugih, primjerice: MySQL, PostgreSQL, Oracle, Sybase,
dBase, IBM DB2 itd.
2.1. Kreiranje baze podataka i tablica
Pokrenuti ćemo SQL Server Management Studio koji će nam omogućiti pregled baza
podataka. Ovisno o instalaciji sustav nas traži lozinku i korisničko ime. Nakon uspješne
prijave, prikazuje se prozor aplikacije vrlo slične strukture kao Visual Studio.
Prema uputama u tablici 1, kreirati ćemo bazu podataka. U stablastom ispisu na Databases
ćemo pritisnuti desni klik i odabrati New Database, nakon toga navodimo ime baze podataka
i završeno je kreiranje. Bazu ćemo nazvati PIDatabase. Postoje još i napredne mogućnosti
kreiranja baze podataka, no kako to nije temelj ovog kolegija i potrebna su određena
predznanja, u ovim materijalima nećemo ići u daljnje razmatranje kreiranje baze podataka.
Tablica 1: Postupak kreiranja baze podataka, dodavanja nove tablice i otvaranja prozora za upite
Kreiranje baze podataka Dodavanje nove tablice Postavljanje upita nad bazom
Nakon uspješno kreirane baze podataka,
unutar datoteke Databases pojaviti će se i
upravo kreirana PIDatabase. Na nju ćemo
ponovno pritisnuti desni klik miša i odabrati
„New Table“. Nakon toga otvara se tablica
koja izgleda poput tablice na slici 1. Dodati
ćemo te atribute i za svakog odabrati tip
podataka iz padajućeg izbornika „Data
Type“. Polje ID će nam biti primarni ključ, to
© 2013, University of Zagreb, Faculty of Organization and Informatics, Varaždin 4
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
ćemo postaviti tako da desnim klikom aktiviramo kontekstni izbornik i odaberemo opciju „Set
primary key“
Slika 2: Automatsko povećavanje primarnog ključa
Obzirom da je primarni ključ prirodni broj i da iza njega ne stoji poslovna logika, možemo
koristiti samo-povećavajuće polje. Da bismo to napravili u donjem prozoru sa svojstvima
proširiti ćemo opciju“Identity specification“, kao na slici 2. Polje „Is Identity“ ćemo postaviti na
Yes, polje „Identity Increment“ ćemo postaviti na 1 (vrijednost za koju se svaki puta kod
dodavanja novog zapisa u bazu, primarni ključ poveća) i polje „Identity Seed“ ćemo postaviti
na 1 (vrijednost od kojeg se primarni ključ počinje brojat).
Da bismo okončali proces kreiranja tablice, kliknuti ćemo na Save. To će nam otvoriti novi
prozor u kojem biramo naziv tablice, napisati ćemo Customer.
2.2. Postavljanje upita
Prije postavljanja upita, moramo otvoriti prozor u kojeg ćemo ih pisati. Da bismo to napravili,
na bazu podataka koju želimo koristiti pritisnemo desni klik i odaberemo opciju „New Query“,
kao na tablici 1. Sada možemo unijeti kod kojim ćemo dodati prvi zapis u bazu podataka:
Kod
insert into Customer (CompanyName, ContactName, ContactTitle, Email, Active) values ('Microsoft', 'Joe Willson', 'MR', '[email protected]', 0);
Konačno, da bismo upit izvršili, označiti ćemo upit koji želimo izvršiti i odabrati ćemo opciju
Execute. Moguće je napisati više upita, a SQL Server će izvršiti samo one označene.
2.3. Pohranjene procedure i okidači
Pohranjena procedura je blok SQL upita koji omogućuje funkcionalnost sličnu kao metoda u
objektno orijentiranom programiranju. Primjerice, niz upita koji rade zapis, validaciju, zamjenu
© 2013, University of Zagreb, Faculty of Organization and Informatics, Varaždin 5
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
podataka itd., pohranimo kao proceduru koju možemo iznova pozivati. Narudžba i ponuda u
bazi podataka mogu biti tablice vrlo slične (često i jednake) strukture. U poslovnom procesu
klijent dobiva ponudu koju može potvrditi. U tom trenutku, da ne bismo ponovno zapisivali
podatke kao narudžbu (ukoliko se ponuda ne promjeni), možemo napraviti proceduru koja će
ponudu pretvoriti u narudžbu. Sljedeći kod prikazuje kako kreirati pohranjenu proceduru koja
aktivira klijenta u bazi podataka. Neka je svaki klijent u bazi neaktivan, sve dok ne naruči
jedan proizvod. Kada ga naruči, korisnik će pokrenuti ActivitySet proceduru (npr. u aplikaciji
odabere opciju Aktiviraj)
Kod
create procedure ActivitySet @CustomerID integer AS update Customer set Active = 1 where ID = @CustomerID; GO
Ponovno označimo kod (upit) procedure i odaberemo Execute. Kao rezultat trebali bismo
dobiti poruku Command(s) completed successfully. Time je procedura pohranjena, a da bismo
je pokrenuli moramo izvršiti sljedeći upit: execute ActivitySet 1;
Ulazi parametar je 1, jer to je primarni ključ retka koji mijenjamo. Ako pogledamo proceduru
onda se vidi da koristimo parametar @CustomerID.
2.4. Okidač
Okidač je pohranjena procedura ili upit koji poziva pohranjenu proceduru koja se automatski
izvršava kao odgovor na neki događaj u bazi podataka. Sljedeći upit prikazuje okidač koji
svaki puta nakon dodavanja klijenta u tablicu Customer automatski radi aktivaciju.
Kod
create trigger UpdateActivityTrigger on Customer after insert as declare @varijabla AS int; set @varijabla = (select id from inserted); execute dbo.ActivitySet @varijabla; print 'Uspjesno sam upisao aktivnost za ' + convert(varchar, @varijabla); go
Command(s) completed successfully.
Nakon izvršavanja upita koji kreira ovaj okidač, svaki puta kada dodamo novi redak dobiti
ćemo poruku o uspješnom zapisu u bazu podataka i poruku od okidača.
Sintaksa okidača je sljedeća:
© 2013, University of Zagreb, Faculty of Organization and Informatics, Varaždin 6
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
Kod
Trigger on an INSERT, UPDATE, or DELETE statement to a table or view (DML Trigger) CREATE TRIGGER [ schema_name . ]trigger_name ON { table | view } [ WITH <dml_trigger_option> [ ,...n ] ] { FOR | AFTER | INSTEAD OF } { [ INSERT ] [ , ] [ UPDATE ] [ , ] [ DELETE ] } [ NOT FOR REPLICATION ] AS { sql_statement [ ; ] [ ,...n ] | EXTERNAL NAME <method specifier [ ; ] > } <dml_trigger_option> ::= [ ENCRYPTION ] [ EXECUTE AS Clause ] <method_specifier> ::= assembly_name.class_name.method_name
2.5. Detach / Attach database
Podaci baze podataka mogu se „otkačiti“ i ponovno „zakačiti“ na istu ili neku drugu instancu
SQL servera. Taj je postupak vrlo koristan zbog migracije baze podataka i tim više što korisnik
koji kasnije koristi bazu podataka u aplikaciji ne mora nužno imati instalaciju SQL Server-a.
Baza podataka koja se otkači zapisana je u .mdf formatu koji je portabilna baza podataka,
odnosno baza podataka u jednoj datoteci. Obzirom na rečeno, imamo dvije mogućnosti
korištenja baze podataka; a) pristupanje preko DBMS-a (u našem slušaju SQL Server), b)
pristupanje kao datoteci (u našem slučaju .mdf)1.
Da bismo otkačili bazu podataka (engl. detach), najprije je moramo ugasiti (Take offline), a
nakon toga pokrenemo postupak kojim se ona otkači od poslužitelja baze podataka.
Možemo to zamisliti kao sljedeće, poslužitelj baze podataka, u našem slučaju SQL Server
2012 je niz utičnica koje sadrže odgovarajući napon i frekvenciju napona, svaki uređaj spojen
na utičnicu je u ovom slučaju jedna baza podataka. Bazu podataka je u ovom slučaju, kao i
neki električni uređaj, moguće isključiti, prenijeti na drugi poslužitelj jednakih karakteristika i
ponovno uključiti. Da bismo to napravili, desnim klikom na bazu podataka u izborniku Tasks
odaberemo opciju Take offline, a nakon toga, ponovno desni klik, izbornik Tasks, opcija
Detach database. Time dobijemo dvije datoteke (.mdf – podaci i .ldf – log podaci).
2.6. Northwind baza podataka
Kako ne bismo radili posebnu bazu podataka (to je gradivo ranijih kolegija) samo za pokazne
primjere ove vježbe, koristiti ćemo pokaznu bazu podataka koja dolazi sa Visual Studijom,
Northwind database. Northwind baza podataka implementira model podataka manje
organizacije i prati proces dobavljanja, naručivanja, prodaje, praćenje klijenata, zaposlenika i
1 http://msdn.microsoft.com/en-us/library/ms190794.aspx
© 2013, University of Zagreb, Faculty of Organization and Informatics, Varaždin 7
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
dostavljača (slika 3). Northwind također sadrži procedure i okidače. U prilogu ove vježbe
dolazi otkačena datoteka Northwind koju ćemo koristiti u Visual Studiu da bismo pokazali
proces kreiranja, prikazivanja, ažuriranja i brisanja podataka putem aplikacije.
Slika 3: Struktura Northwind baze podataka - nije u pravilnoj ERA notaciji, već u MS SQL Server notaciji
3. Pristupanje bazi podataka korištenjem DataSet-ova. DataSet je klasa koja omogućuje offline pristup bazi podataka i njeni objekti predstavljaju
memorijske reprezentacije dohvaćenih podataka iz nekog izvora podataka (ne mora biti baza
podataka iako najčešće jest). DataSet predstavlja sve podatke uključujući tablice, ograničenja i
veze između tablica.
Slika 4: DataSet2
2 http://msdn.microsoft.com/en-us/library/ms180730(v=vs.90).aspx
© 2013, University of Zagreb, Faculty of Organization and Informatics, Varaždin 8
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
Slika 5: Glavni izbornik aplikacije
Promotrimo sliku 4. Na lijevom rubu slike nalazi se neki izvor podataka (XML datoteka ili baza
podataka), a na desnom rubu slike nalazi se korisnik koji pregledava podatke pomoću
DataGrid kontrole. Korištenjem DataSeta procedura za dobavljanje podataka je sljedeća.
Korisnik trži neke podatke za ispis na DataGrid kontrolu. DataGrid kontrola pomoću
BindingSource klase povezana je sa podacima. BindingSource ponaša se kao izvor podataka
za neku kontrolu (primjerice TextBox, ComboBox ili DataGridView). Svaku promjenu korisnika
propagira na sljedeći sloj prema bazi podataka, a svaku promjenu baze podataka propagira
dalje prema korisniku. Ukratko omogućuje „vezanje“ kontrole za podatak. Te podatke dobiva
iz DataSet kontrole koja je memorijska preslika baze podataka, a ta memorijska preslika baze
podataka puni se pomoću TableAdapter klase. Dakle korisnik zatraži podatke, BindingSource
potraži te podatke u DataSet-u, kojeg je prethodno napunilo TableAdapter. TableAdapter
sadrži upite prema kojima ima mogućnost filtrirati DataSet. Ukoliko korisnik mijenja podatke,
oni će se putem BindingSource-a mjenjati samo do DataSet-a. Tek nakon što korisnik
odabere „Save“ (ili programer tako isprogramira), podaci iz DataSet-a preslikavaju se u bazu
podataka. Više o tome na http://blogs.msdn.com/b/bethmassi/archive/2007/09/19/binding-
multiple-comboboxes-to-the-same-datasource.aspx.
3.1. Kreiranje nove aplikacije sa pristupom podacima
Kreiranje aplikacije s modalnim prozorima
Nakon što smo kreirali Windows Forms projekt, Form1 ćemo preimenovati u frmMain i urediti
svojstva:
Text ACME d.o.o.
StartPosition CenterScreen
IsMdiContainer True
Ovo zadnje svojstvo nam omogućuje kreiranje forme
koja može ugnijezditi druge forme. Na frmMain ćemo
još dodati MenuStrip kontrolu koja će biti glavni
izbornik aplikacije. Strukturu izbornika ćemo napraviti
tako da File sadrži opciju Exit, a Data sadrži opcije za
prikaz tablica iz baze podataka kao na slici. Name
svojstvo izbornika ćemo postaviti msMain, a svaki
element izbornika ćemo početi prefiksom „mi“ (kao menu item) i nastaviti sa strukturom
izbornika. Prema slici, Orders opcija će se zvati miDataBrowseOrders, opcija Browse će se
zvati miDataBrowse.
© 2013, University of Zagreb, Faculty of Organization and Informatics, Varaždin 9
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
Slika 6: Dodavanje izvora podataka
3.2. Spajanje na bazu podataka
Kao što smo najavili, za ovu vježbu koristiti
ćemo pokaznu bazu podataka Northwind koja
je u obliku Microsoft SQL Database datoteke.
Prvi korak je dodavanje izvora podataka (Data
Source). U izborniku DataSources (ukoliko nije
vidljiv, unutar izbornika View, Other Windows,
Data Sources) odaberemo Add new datasource.
Nakon pokretanja „čarobnjaka“ za
dodavanje novog izvora podataka, odabrati
ćemo bazu podataka (Database), nakon toga DataSet. Iz sljedećeg izbornika kliknuti ćemo na
gumb New Connection. Na novom prozoru ima nekoliko zanimljivih opcija. Gumbom Change
se otvara novi prozor na kojem biramo tip baze podataka na kakvu se spajamo. U ovom
prozoru možemo postaviti korisničko ime, lozinku, kreirati novu bazu podataka itd. Mi ćemo
odabrati Change… i odabrati Microsoft SQL Server Database File.
Lociranje datoteke Testiranje veze prema bazi podataka
Nakon toga će se dialog s kojeg smo krenuli promijeniti i tražiti će nas lokaciju .mdf datoteke.
Kada smo je pronašli, testirati ćemo vezu prema bazi podataka pritiskom gumba „Test
Connection“. Ako je rezultat „Test connection succeded“ tada je baza podataka spremna za
korištenje i možemo kliknuti na OK.
© 2013, University of Zagreb, Faculty of Organization and Informatics, Varaždin 10
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
Slika 8: Tablice koje ćemo koristiti
Slika 7: Želimo li presnimati datoteku baze podataka u projekt?
Nakon tog koraka otvara se prozor koji nas želimo li presnimiti bazu podataka u projekt, mi
ćemo odabrati NE.
U posljednjem koraku moramo odabrati koje ćemo
sve tablice, poglede, procedure i funkcije iz baze
podataka koristiti. Kao i na slici odaberemo
Categories, Customers, Employees, Order Details,
Orders, Products i Suppliers. Nećemo koristiti sve
tablice, već ćemo pokazati samo jedan CRUD primjer a
ostatak ostavljamo čitateljima za implementaciju.
3.3. Prikaz podataka – READ
Podatke ćemo prikazivati na prozoru kojeg ćemo aktivirati iz izbornika. Napraviti ćemo novi
direktorij u strukturi projekta i nazvati ga DataBrowseForms. Unutar tog direktorija ćemo
dodati novu formu i nazvati je frmBrowseOrders. Unutar izbornika Data, Browse, Orders
odabrati ćemo novu metodu za rukovanje događajem MouseUp i tu ćemo pokretati formu za
prikaz narudžbi:
Kod
private void miDataBrowseOrders_MouseUp(object sender, MouseEventArgs e) { DataBrowseForms.frmBrowseOrders browseOrdersFrom = new DataBrowseForms.frmBrowseOrders(); browseOrdersFrom.MdiParent = this; //<- postavlja prozor kao dijete od frmMain browseOrdersFrom.WindowState = FormWindowState.Maximized; browseOrdersFrom.Show(); }
© 2013, University of Zagreb, Faculty of Organization and Informatics, Varaždin 11
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
Ona će nam poslužiti za prikaz narudžbi i stavki narudžbi. Za to moramo napraviti sljedeće:
1. Dodati DataGridView kontrole za narudžbe (Orders) i stavke narudžbi (Order Details).
To ćemo napraviti tako da iz DataSources prozora kliknemo na tablicu i dovučemo je
na prozor. To napravimo za svaku tablicu.
2. Sada ćemo promjeniti svojstva forme (Text = Browse orders, StartPosition=
CenterParent)
3. Za DataGridView kontrole koje smo dodali promijenimo svojstvoj Anchor da dobijemo
otprilike jednaki izgled kao i na slici:
Slika 9: Pripremljene DataGridView kontrole
4. Za DataGridView kontrole svojstvo SelectionMode ćemo postaviti na FullRowSelect,
svojstvo AllowUsersToAddRows = false.
Možemo pokrenuti aplikaciju i primijetiti da se ispisuju podaci, no tablica sa narudžbama
nije povezana sa tablicom stavki. Korisnik želi takav prikaz da svaki puta kada označi neku
narudžbu, vidi njene detalje, odnosno stavke. Pogledajmo programski kod koji se nalazi
ispod ove forme:
Kod
private void ordersBindingNavigatorSaveItem_Click(object sender, EventArgs e) { this.Validate(); this.ordersBindingSource.EndEdit(); this.tableAdapterManager.UpdateAll(this.northwndDataSet); } private void frmBrowseCategories_Load(object sender, EventArgs e) { // TODO: This line of code loads data into the 'northwndDataSet.Order_Details' table. You can move, or remove it, as needed. this.order_DetailsTableAdapter.Fill(this.northwndDataSet.Order_Details); // TODO: This line of code loads data into the 'northwndDataSet.Orders' table. You can move, or remove it, as needed. this.ordersTableAdapter.Fill(this.northwndDataSet.Orders); }
© 2013, University of Zagreb, Faculty of Organization and Informatics, Varaždin 12
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
Slika 10: Dodavanje novog upita na
TableAdapter
Prva metoda izvršava se kada korisnik u „Binding Navigator“ kontroli pritisne na ikonu za
spremanje. Pokrene se postupak validacije podataka, zatvara se BindingSource i TableAdapter
preslikava sadržaj našeg DataSet-a u bazu podataka (vidi uvodni tekst). Druga metoda,
prilikom učitavanja forme pročita podatke iz baze u tablice unutar DataSet-a. DataGridView
kontrole povezane preko BindingSource-a na northwindDataSet. Za svaki DataGridView to je
moguće vidjeti u svojstvu DataSource. Ono što želimo jest OrderDetails tablicu puniti ovisno
o odabranom primarnom ključu iz Orders tablice. Za to moramo napraviti novi upit u bazi
podataka.
5. Da bismo kreirali novi upit iz Solution Explorer
prozora odabrati ćemo northwindDataSet.xsd
pronaći tablicu Order Details i u njezin
TableAdapter kliknuti desnim gumbom miša.
Odabiremo opciju Add Query… kao na slici.
U sljedećem prozoru koji se otvori, odabrati ćemo
„Use SQL statements“, nakon toga „SELECT which
returns rows“ i zatim odaberemo Query Builder i
podesimo upit tako da vraća samo one retke od
određene narudžbe. Napravimo novu varijablu i
nazovemo je OrderID
Slika 11: Query Builder
Možemo testirati upit da vidimo dobivamo li dobre rezultate. Nakon toga, odabiremo „Next“
i promjenimo nazive metoda. Ono što se događa u pozadini jest da će Visual Studio
generirati metode na TableAdapter-u za Order Details tablicu, pa ćemo umjesto dosadašnje
metode Fill (vidi raniji kod), pozivati novu metodu (prema slici).
© 2013, University of Zagreb, Faculty of Organization and Informatics, Varaždin 13
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
Slika 12: Odabir naziva metoda za punjenje DataTable-a
Sada tablica izgleda nešto drugačije, odnosno vidljiv nam je novi, upravo dodani upit.
Slika 13: Konačan izgled TableAdapter-a nakon dodavanja novog upita
Vraćamo se u frmBrowseOrders dizajner i dodati ćemo novu metodu za rukovanje
događajem SelectionChanged nad kontrolom ordersDataGridView, te promjeniti raniju
metodu za rukovanje događajem Load:
Kod
private void frmBrowseOrders_Load(object sender, EventArgs e) { this.ordersTableAdapter.Fill(this.northwndDataSet.Orders); } private void ordersDataGridView_SelectionChanged(object sender, EventArgs e) { if (ordersDataGridView.RowCount > 0) { int orderID = int.Parse(ordersDataGridView.CurrentRow.Cells[0].Value.ToString()); this.order_DetailsTableAdapter.FillByOrderID(this.northwndDataSet.Order_Details, orderID); } }
Ako sada pokrenemo aplikaciju i navigiramo kontrolom za prikaz narudžbi, stavke će se
mijenjati i prikazivati samo one za narudžbu koju promatramo.
Fino podešavanje prikaza DataGridView kontrole
© 2013, University of Zagreb, Faculty of Organization and Informatics, Varaždin 14
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
Kao što možete uočiti neki atributi tablice Orders i Order Details su nepotrebni ili nejasni.
Primjerice, CustomerID, EmployeeID ili RequiredDate nam ne znače mnogo isto kao iz
ProductID nismo sigurni o kojem se proizvodu radi toliko dugo dok ne znamo šifru. Najprije
ćemo neke atribute sakriti, a ProductID ćemo izmijeniti tako da prikazuje naziv, a ne šifru.
Odabrati ćemo orderDataGridView i u njenom gornjem desnom kutu kliknuti na malu ikonu
trokuta.
Slika 14: Izbornik za fino podešavanje DataGridView kontrole
Pojaviti će se izbornik kao na slici na kojem trebamo odabrati Edit Columns… Time dobivamo
detaljan prikaz svih redaka te možemo mijenjati njihov tip, naziv, prikaz itd. Za Kolone
CustomerID, EmployeeID i RequiredDate ćemo postaviti na Visible = false.
Slika 15: Uređivanje stupaca
Slično ćemo napraviti i za order_DetailsDataGridView. Umjesto da vidimo šifre, ProductID
želimo korisniku prikazati naziv proizvoda. Da bismo to omogućili za ColumnType ćemo
odabrati DataGridViewComboBoxColumn i kao na slici ćemo odabrati novi DataSource,
tablicu Products iz northwindDataSet.
© 2013, University of Zagreb, Faculty of Organization and Informatics, Varaždin 15
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
Slika 16: Uređivanje izvora podataka, podataka za prikaz i podatka za selekciju
Nakon toga imamo mogućnost napraviti razliku između toga što korisniku prikazujemo, a što
će VisualStudio u pozadini koristiti i to preko DisplayMember opcije koju ćemo postaviti na
ProductName, a ValueMember na ProductID. Time prikazujemo naziv a koristimo šifru. Da bi
tablica i dalje izgledala kao tablica (bez kolone sa ComboBox kontrolom) unutar kategorije
Apperence, za DisplayStyle ćemo odabrati Nothing i kao naziv kolone (Header text) ćemo
staviti Product.
Pokrenemo aplikaciju.
Slika 17: Aplikacija - promjenjeni izgled stupca vanjskih ključeva
Primijetite da sada kako pretražujemo elemente, više se ne prikazuje šifra, već naziv artikla i
time je završen Read.
3.4. Brisanje podataka - Delete
Ukoliko ništa ne diramo, aplikacija koju smo do sada napravili omogućiti će brisanje. Kada
smo prvi puta dodali ordersDataGridView kontrolu, VisualStudio je generirao i
BindingNavigator kontrolu sa prikazom trenutne pozicije, gumbima za pomicanje po tablici,
gumbima za spremanje, brisanje i dodavanje novih zapisa.
© 2013, University of Zagreb, Faculty of Organization and Informatics, Varaždin 16
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
Možemo probati koristiti tipku brisanja. Primjetite da ukoliko ne odaberemo opciju Save,
podaci se neće obrisati. To je upravo zbog DataSet-a. Nama se ne sviđa ova generirana
metoda za brisanje, već želimo vlastitu i to takvu, da korisnika pitamo dali je siguran želi li
obrisati zapis. Za to, u dnu dizajnera odaberemo ordersBindingNavigator i postaviti svojstvo
DeleteItem postaviti na (none). Dva puta ćemo kliknuti na opciju za brisanje kako bi nam se
generirala metoda za rukovanje klikom.
Obzirom da su nam narudžbe vezane uz detalje narudžbi, odnosno stavke, ne možemo
narudžbu toliko dugo obrisati dok postoji stavaka, stoga, moramo najprije obrisati sve stavke,
a onda tek narudžbu. To možemo napraviti na nekoliko načina, no mi ćemo napisati
jednostavan kod koji će to napravit. Kliknuti ćemo na ikonu za brisanje i izmijeniti kod
metoda.
Kod
private void ordersBindingNavigatorSaveItem_Click(object sender, EventArgs e) { this.Validate(); this.order_DetailsBindingSource.EndEdit(); this.ordersBindingSource.EndEdit(); this.tableAdapterManager.UpdateAll(this.northwndDataSet); } private void bindingNavigatorDeleteItem_Click(object sender, EventArgs e) { if (MessageBox.Show("Do you whish to delete this order?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes) { //delete order details for (int i = 0; i < order_DetailsDataGridView.Rows.Count; i++) { order_DetailsDataGridView.Rows.RemoveAt(i); } ordersDataGridView.Rows.RemoveAt(ordersDataGridView.CurrentRow.Index); } }
3.5. Dodavanje novih redaka – Create
Ono što sada želimo napraviti je dodavanje novih narudžbi. Za to moramo imati novu formu
koja će prihvaćati podatke i zapisivati ih u bazu. No svaka narudžba ima neke stavke, stoga
moramo napraviti i formu koja će omogućiti dodavanje stavaka. Kada korisnik dobije novi
prozor sa mogućnošću kreiranja narudžbe, postaviti ćemo gumb kojim će se narudžba
spremiti (kako bismo dobili primarni ključ iz baze podataka), proslijediti ključ putem
konstruktora forme za dodavanje stavaka i vezati nove stavke uz ključ upravo kreirane
narudžbe.
© 2013, University of Zagreb, Faculty of Organization and Informatics, Varaždin 17
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
Formu za dodavanje narudžbe kreirati ćemo unutar novog foldera našeg Solution Explorera,
DataCreateForms i nazvati ju frmCreateOrder. Da bismo je prikazali, u
orderBindingNavigatoru ćemo opciju AddNewItem postaviti na (none) i dodati metodu za
rukovanje klikom.
Kod
private void bindingNavigatorAddNewItem_Click(object sender, EventArgs e) { DataCreateForms.frmCreateOrder frmOrder = new DataCreateForms.frmCreateOrder(); frmOrder.ShowDialog(); //<- dialog ne dozvoljava fokus drugih kontroli }
A na novu formu, ovaj put nećemo dovlačiti tablicu iz izbornika DataSources, već element po
element. Visual Studio će nam generirati labelu i kontrole za odabrane tipove podataka, koje
su već povezane na bazu podataka (engl. Binding). Da nisu povezane, morali bismo imati kod
koji svaku vrijednost čita iz određene kontrole (npr. TextBox) i stavlja ih u upit za kreiranje
zapisa. Prije nego što počnemo dovlačiti atribute na kontrole, za CustomerID i EmployeeID za
vrstu kontrole odabrati ćemo ComboBox. Napraviti ćemo kontrolu da nam izgleda kao slika:
Slika 18: Uređivanje forme za dodavanje nove narudžbe - ComboBox zamjena
Kao što smo ranije kod DataGridView kontrole
odabirali ValueMember i DisplayMember,
ovdje ćemo napraviti slično. Klikom trokuta na
customerIDComboBox, za DataSource ćemo
odabrati Customers, za DisplayMember
CustomerName, za ValueMember CustomerID
i za SelectedValue CustomerID. SelectedValue
se u ovom slučaju odnosi na vezu prema
trenutnoj Narudžbi. Obzirom da smo za
DataSource odabrali Customers tablicu,
© 2013, University of Zagreb, Faculty of Organization and Informatics, Varaždin 18
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
kontrolu smo razdvojili od Orders tablice, pa pomoću SelectedValue odabiremo da nam
unutar konteksta orderBindingSource SelectedValue bude ValueMember.
Visual Studio je generirao novu kontrolu BindingNavigator koju nećemo koristiti, pa je
možemo obrisati. Umjesto toga dodati ćemo tri nova gumba: „…“ (btnAddDetails) koji će nam
služiti za otvaranje stavki, „Create“ kojim ćemo napraviti narudžbu i „Clear“ pomoću kojeg
zatvaramo prozor.
Sada ćemo dodati kod za MouseUp događaje na te gumbe:
Kod (konstruktor kod frmCreateDetails)
private void btnCreate_MouseUp(object sender, MouseEventArgs e) { createNewEntry(); } private void createNewEntry() { this.Validate(); this.ordersBindingSource.EndEdit(); this.tableAdapterManager.UpdateAll(this.northwndDataSet); } private void btnAddDetails_MouseUp(object sender, MouseEventArgs e) { createNewEntry(); int OrderId = (int)northwndDataSet.Orders.Rows[0]["OrderID"]; // frmCreateDetails ćemo kreirati nešto kasnije, no ovdje prosljedimo ID frmCreateDetails frmCreateDetails = new frmCreateDetails(OrderId); if (Editing) frmCreateDetails.Editing = true; frmCreateDetails.ShowDialog(); } private void btnClear_MouseUp(object sender, MouseEventArgs e) { this.Close(); }
Također, želimo da čim se otvori ovaj prozor, korisnik već uređuje novu narudžbu, pa
moramo promjeniti metodu Load.
Kod (konstruktor kod frmCreateDetails)
public frmCreateOrder() { InitializeComponent();} private void frmCreateOrder_Load(object sender, EventArgs e) { this.employeesTableAdapter.Fill(this.northwndDataSet.Employees); this.customersTableAdapter.Fill(this.northwndDataSet.Customers); ordersBindingSource.AddNew(); }
© 2013, University of Zagreb, Faculty of Organization and Informatics, Varaždin 19
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
Sada imamo sav kod koji nam je potreban da bismo kreirali i spremili nove narudžbe. (OPREZ,
neka su polja obavezna, pa ovdje treba još finog podešavanja i interakcije s korisnikom)
3.6. Dodavanje stavki
Kreirati ćemo novu formu unutar direktorija DataCreateForms i nazvati je frmCreateDetails.
Promjeniti ćemo joj svojstvo Text (Add order details) i na sličan način kao ranije povući
tekstualna polja iz DataSources izbornika, no ovaj put ćemo povući i čitavu tablicu u obliku
DataGridView kontrole kako bismo vidjeli stavke koje smo dodali do sada. Uz to, pored
productIDTextBox kontrole ćemo dodati gumb „…“, koji će nam kasnije prikazati listu svih
proizvoda i u taj TextBox zapisati šifru odabranog proizvoda.
Slika 19: Forma za dodavanje stavki narudžbe
Kao i za dodavanje narudžbi, moramo podesiti formu tako da kad je korisnik otvori,
automatski se dodaje novi zapis, a kada klikne na „…“, otvara se forma sa proizvodima i
ona ima mogućnost vratiti ProductID i UnitPrice. Da bismo mogli vratiti šifru proizvoda i
cijenu, trebamo tablicu sa proizvodima. Idemo u direktorij DataBrowseForms i dodajemo
novu formu frmBrowseProducts. U nju ćemo iz DataSource kontrole povući tablicu
Products i napraviti sve promjene (postavke svojstva, selekcije, dodavanje novog
elementa u glavni izbornik, otvaranje forme na klik, sve kao i za frmBrowseOrders). Kako
želimo da nam ta tablica vraća vrijednosti, trebamo napraviti nova svojstva koja ćemo
čitati i gumbe koji će upravljati formom.
© 2013, University of Zagreb, Faculty of Organization and Informatics, Varaždin 20
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
Slika 20: Forma za pretraživanje proizvoda koja vraća vrijednost odabira - Lookup
Otvoriti ćemo formu frmBrowseProducts i dodati ćemo svojstva; ProductID i UnitPrice te
njihove gettere i sttere. Kada korisnik klikne na dataGridView kontrolu ta će se svojstva
postaviti, a njih ćemo moći dohvatiti i zapisati vrijednosti u polja koja nedostaju. Stoga ćemo
morati obraditi događaj selekcije i još moramo iz tablice čitati vrijednosti. Da bismo to lakše
napravili moramo si unutar productsDataGridView kontrole postaviti imena.
Kao što slika prikazuje odabiremo opciju najprije ProductID pa UnitPrice i mijenjamo svojstvo
DataPropertyName u ProductIDColumn i UnitPriceColumn.
Slika 21: Imenovanje stupaca
Sada možemo napisati kod kojim postavljamo vrijednosti svojstava. Dodajemo novu metodu
za obradu događaja SelectionChanged nad kontrolom productsDataGridView.
© 2013, University of Zagreb, Faculty of Organization and Informatics, Varaždin 21
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
Kod
public int ProductID { get; set; } public float UnitPrice { get; set; } private void productsDataGridView_SelectionChanged(object sender, EventArgs e) { this.ProductID = int.Parse(productsDataGridView["ProductIDColumn", productsDataGridView.CurrentRow.Index].Value.ToString()); this.UnitPrice = float.Parse(productsDataGridView["UnitPriceColumn", productsDataGridView.CurrentRow.Index].Value.ToString()); }
Na gumb OK ćemo zatvarati formu (kasnije se to može izmjeniti po potrebi).
* * *
Sada se možemo vratiti na frmCreateDetails i možemo obraditi MouseUp događaj za gumb
„…“.
Kod
private void btnListProducts_Click(object sender, EventArgs e) { DataBrowseForms.frmBrowseProducts frmProducts = new DataBrowseForms.frmBrowseProducts(); frmProducts.ShowDialog(); productIDTextBox.Text = frmProducts.ProductID.ToString(); unitPriceTextBox.Text = frmProducts.UnitPrice.ToString(); }
Pomoću tog koda dohvatili smo vrijednosti i zapisali ih unutar productIDTextbox kontrole i
unitPriceTextBox kontrole koje su već vezane za bazu podataka. Time je postupak dodavanja
stavki skoro završen, no ono što još moramo napraviti jest prosljeđivanje šifre narudžbe na
koju vežemo stavke, stoga promjenimo konstruktor (čime i raniji kod na frmCreateOrder za
btnAddDetails_MouseUp):.
Kod (konstruktor kod frmCreateDetails)
public int OrderId { get; set; } public frmCreateDetails(int orderId) { InitializeComponent(); this.OrderId = orderId; }
Također ćemo izmijeniti kod za spremanje i dodavanje elementa. Najprije za
order_DetailsBindingNavigator treba promjeniti svojstvo AddNewItem na none. A nakon toga
ćemo dodati metodu koja obrađuje događaj klik za bindingNavigatorAddNewItem i za
order_DetailsBindingNavigatorSaveItem. Kod će izgledati ovako:
© 2013, University of Zagreb, Faculty of Organization and Informatics, Varaždin 22
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
Kod
private void frmCreateDetails_Load(object sender, EventArgs e) { this.productsTableAdapter.Fill(this.northwndDataSet.Products); this.order_DetailsTableAdapter.FillByOrderID(this.northwndDataSet.Order_Details, OrderId); // moramo napraviti filtriranje za samo one stavke koje dodajemo } private void order_DetailsBindingNavigatorSaveItem_Click(object sender, EventArgs e) { SaveCurrent(); } private void bindingNavigatorAddNewItem_Click(object sender, EventArgs e) { addNewEntry(); } private void addNewEntry() { try { this.order_DetailsBindingSource.AddNew(); orderIDTextBox.Text = OrderId.ToString(); } catch (Exception ex) { MessageBox.Show("Exception: " + ex.Message); } } private void SaveCurrent() { this.Validate(); this.order_DetailsBindingSource.EndEdit(); this.tableAdapterManager.UpdateAll(this.northwndDataSet); }
Time smo završili kod za dodavanje zapisa u tablicu Order i OrderDetails.
3.7. Ažuriranje zapisa - Update
Da bismo omogućili ažuriranje trebamo napraviti minimalne promjene na postojećim
formama. Naime, kako koristimo kontrole koji su vezani za podatke (engl. data bound
controls) puno nam je lakše napraviti ažuriranje jer podatke koje prikazujemo možemo
mjenjati i spremati. Ono što nam preostaje je eliminirati automatsko dodavanje redaka
prilikom otvaranja prozora za dodavanje novih redaka. Iste ćemo koristiti i za ažuriranje.
Stoga, najprije ćemo promjeniti formu za narudžbe, odnosno frmCreateOrder.
Kod
private bool Editing { get; set; }
© 2013, University of Zagreb, Faculty of Organization and Informatics, Varaždin 23
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
public int OrderID { get; set; } public frmCreateOrder() { InitializeComponent(); OrderID = -10; //<- mora biti postavljena pa koristimo neutralnu vrijednost -10 } // preopterećenje konstruktora (ovaj ćemo konstruktor koristiti kada korisnik odabere ažuriranje public frmCreateOrder(int OrderID) { InitializeComponent(); this.OrderID = OrderID; this.Editing = true; } private void frmCreateOrder_Load(object sender, EventArgs e) { this.employeesTableAdapter.Fill(this.northwndDataSet.Employees); this.customersTableAdapter.Fill(this.northwndDataSet.Customers); if (this.OrderID != -10) { this.ordersTableAdapter.FillByOrderID(this.northwndDataSet.Orders, this.OrderID); // ako je ažuriranje popuni prema ID-u } else { ordersBindingSource.AddNew(); // ako nije ažuriranje } }
Sada znamo koju narudžbu uređujemo i znamo da je uređujemo pa te iste podatke možemo
proslijediti i formi za dodavanje stavki:
Kod
private void btnAddDetails_MouseUp(object sender, MouseEventArgs e) { createNewEntry(); int OrderId = (int)northwndDataSet.Orders.Rows[0]["OrderID"]; frmCreateDetails frmCreateDetails = new frmCreateDetails(OrderId); if (Editing) frmCreateDetails.Editing = true; frmCreateDetails.ShowDialog(); }
A u formi za dodavanje stavki samo moramo osigurati da se ne dodaje novi redak čim se
forma otvori, pa ćemo i njezin kod izmjeniti:
© 2013, University of Zagreb, Faculty of Organization and Informatics, Varaždin 24
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
Kod
public int OrderId { get; set; } public bool Editing { get; set; } public frmCreateDetails(int orderId) { InitializeComponent(); this.OrderId = orderId; Editing = false; } private void frmCreateDetails_Load(object sender, EventArgs e) { this.productsTableAdapter.Fill(this.northwndDataSet.Products); this.order_DetailsTableAdapter.FillByOrderID(this.northwndDataSet.Order_Details, OrderId);
if (!Editing) { addNewEntry(); }
}
I sada možemo dodati kontekstni izbornik, koji će se pojaviti kada unutar tablice
frmBrowseOrders kliknemo desni gumb miša, a sadržava opciju ažuriranja. Za to, iz izbornika
sa kontrolama dodajemo novi ContextStripMenu i nazovemo ga ordersContextStripMenu.
Unutar njega slično kao i za glavni izbornik dodajemo novu opciju Edit i na nju metodu za
rukovanje događajem MouseUp. Prije toga, moramo obraditi klik desnog gumba miša na
ordersDataGridView kontrolu koja će prikazati izbornik i označiti redak (jer tako možemo
dohvatiti šifru). Moramo simulirati klik miša i označavanje redka. Konačan kod izgleda:
Kod
private void ordersDataGridView_MouseDown(object sender, MouseEventArgs e) { if (e.Button == System.Windows.Forms.MouseButtons.Right) { DataGridView.HitTestInfo hitTest = ordersDataGridView.HitTest(e.X, e.Y); ordersDataGridView.ClearSelection(); ordersDataGridView.Rows[hitTest.RowIndex].Selected = true; ordersContextStripMenu.Show(ordersDataGridView,e.Location); } } private void editToolStripMenuItem_MouseUp(object sender, MouseEventArgs e) { int OrderID = int.Parse(ordersDataGridView.SelectedRows[0].Cells["OrderIDColumn"].Value.ToString()); DataCreateForms.frmCreateOrder order = new DataCreateForms.frmCreateOrder(OrderID); order.ShowDialog(); }
© 2013, University of Zagreb, Faculty of Organization and Informatics, Varaždin 25
Katedra za razvoj informacijskih sustava
Programsko inženjerstvo, akademska godina: 2012/13
4. Pitanja za ponavljanje
1. Što je DataSet?
2. Što je okidač (trigger) u bazi podataka?
3. Navedite primjer okidača (triggera) i scenarij korištenja.
4. Što je pohranjena procedura?
5. Dali se podaci u DataSetu automatski ažuriraju u bazi podataka?
6. Što je TableAdapter?
7. Što je Identity polje?
8. Čemu služi attach/detach baze podataka?
9. Što je MDI container?
10. Što je data binding?
5. Literatura (pristupano u periodu ljetnog semestra ak.g.
2012/2013) 1. http://msdn.microsoft.com/en-us/library/ss7fbaez.aspx
2. http://msdn.microsoft.com/en-us/library/h43ks021.aspx
3. http://msdn.microsoft.com/en-us/library/ms189799.aspx