Documentos de Académico
Documentos de Profesional
Documentos de Cultura
01 Ado - Net Profesional PDF
01 Ado - Net Profesional PDF
NET
1
okruženje
U ovom poglavlju napravićemo kratak pregled programa ADO.NET i pokazaćemo vam delove
koda, što je, složićete se, najbolji način da se savlada ovaj koncept. Nadamo se da će vam ovo
poglavlje obezbediti solidno razumevanje osnova funkcionisanja ADO.NET, kao i da ćete do
kraja ovog poglavlja biti ubeđeni u sve prednosti ADO.NET.
ADO.NET je najnovija tehnologija pristupa podacima u velikom nizu Microsoftovih
tehnologija. Međutim, pomenuti program razlikuje se od prethodnih tehnologija po tome što je
stvoren kao deo potpuno nove platforme koja se naziva .NET razvojno okruženje. Ova
platforma je podešena tako da izvrši revoluciju u svakoj oblasti razvoja gde je ADO.NET samo
jedan njegov aspekt. Stoga ćemo početi istraživanjem glavnih karakteristika .NET okruženja.
Veliki broj jezika (poput COBOL, Perl i Eiffel), kao i navedenih Microsoft jezika obezbeđeni su
od strane nezavisnih kompanija (detaljnije informacije za navedena tri jezika možete pronaći na
sledećim vezama:
http://www.adtools.com/donet/index.html za COBOL,
http://aspn.activestate.com/ASPN/Downloads/PerlASPX/More za Perl i
http://msdn.microsoft.com/library/techart/pdc_eiffel.htm za Eiffel).
10
Pristup podacima i .NET okruženje
Sklopovi
.NET kôd se razvija kao sklop (engl. assembly). Sklopovi se sastoje iz kompajliranih IL kodova i
pritom moraju da sadrže jednu primarnu datoteku (osim u slučaju dinamičkih sklopova koji se u
potpunosti skladište u memoriji). Pomenuta datoteka može biti izvršna datoteka (.exe), DLL ili
kompajlirana ASP.NET Web aplikacija ili Web servis. Sklop može da sadrži resursne datoteke
(poput slika i ikona) i ostale module koda, kao i svaka primarna datoteka. Međutim, kao
najbitnije, sklopovi mogu da sadrže metapodatke. Pomenuti metapodaci sastoje se iz dva dela: tip
metapodatka sadrži informaciju o svim izvezenim tipovima i njihovim metodama koji su
definisani u sklopu. .NET sklopovi, kao i IL kodovi, sadrže deo koji se zove manifest. Ovaj deo
sadrži metapodatke sklopa (engl. assembly metadata) ili informaciju o samom sklopu, kao što su broj
verzije i broj izgradnje.
Pomenuti metapodaci dozvoljavaju sklopu da u potpunosti bude samoopisiv. Naime, sklop
sadrži sve informacije potrebne za instaliranje i aktiviranje aplikacije, te stoga nema potrebe za
bibliotekama tipa ili registara unosa. Pomenuti proces instaliranja može biti jednostavan kao i
proces kopiranja sklopa na ciljnu mašinu. Samim tim što sklop sadrži informacije o verziji, više
verzija iste komponente mogu se instalirati zajedno na istoj mašini. Upravo ova mogućnost
rešava problem poznat kao „DLL pakao” (engl. DLL Hell), gde aplikacija koja instalira novu
verziju postojeće komponente prekida programe koji koriste staru verziju.
11
Poglavlje 1
12
Pristup podacima i .NET okruženje
ODBC
Microsoft je ranih 90-ih godina u saradnji sa drugim kompanijama razvio tzv. povezivost otvorenih
baza podataka (engl. Open Database Connectivity) ili skraćeno ODBC, i to kao rešenje prethodno
napomenutom problemu. Ovim se obezbedio zajednički sloj pristupa podacima koji se mogao
koristiti za pristupanje skoro svakom sistemu upravljanja relacionom bazom podataka (RDBMS).
Naime, ODBC koristi specifičan RDBMS upravljački program za komuniciranje sa izvorom
podataka. ODBC upravljački program (engl. Driver Manager) učitava i upravlja pomenutim
upravljačkim programom (ponekad su u pitanju samo ovojnice matičnih API poziva). Ovim je
takođe obezbeđena karakteristika poput udruživanja veza (engl. connection pooling) – sposobnost da
se ponovo upotrebe povezivanja, umesto uništavanja istih pri njihovom zatvaranju i stvaranja
novog povezivanja svaki put kada se pristupi bazi podataka. Naime, aplikacija komunicira sa
upravljačkim programom kroz standardni API, te stoga (teorijski gledano), ako želimo da
ažuriramo aplikaciju kako bismo se povezali sa različitim sistemom upravljanja relacionom bazom
podataka (RDBMS), potrebno je da promenimo samo detalje povezivanja (u praksi, postojale su
određene razlike u SQL dijalektu). Međutim, jedna od najbitnijih karakteristika ODBC-a je
činjenica da je ODBC bio otvoreni standard prihvaćen čak i od strane asocijacije Open Source.
Kao rezultat, ODBC upravljački programi razvijeni su za mnoge sisteme baze podataka kojima se
ne može direktno pristupiti pomoću kasnijih tehnologija pristupa podacima. Kao što ćemo ubrzo
videti, ovo znači da će ODBC tek odigrati svoju ulogu u konjukciji sa ADO.NET-om.
DAO
Jedan od problema vezanih za ODBC jeste da je dizajniran za upotrebu iz jezika niskog nivoa
poput C++. Naime, uporedo sa rastom važnosti programa Visual Basic, rasla je i potreba za
tehnologijom pristupa podacima koji bi se koristili na jednostavniji način iz VB-a. Ovaj problem
rešen je u VB 3 stvaranjem objekata pristupa podacima (Data Access Objects – DAO). Naime, DAO
je obezbedio jednostavan model objekta za komuniciranje sa Jetom, mehanizmom baze
podataka u pozadini Microsoft Access radne površine baze podataka. DAO je optimizovan za
Access (iako se može upotrebiti za povezivanje sa ODBC izvorima podataka) i predstavlja
najbrži način za komuniciranje sa Accessom iz VB 6.
13
Poglavlje 1
RDO
Zbog optimizacije za Access, DAO je postao prespor za upotrebu sa ODBC izvorima podataka.
Da bi rešio problem, Microsoft je u verziji VB 4 (32-bitna verzija) predstavio tzv. udaljene
objekte podataka (Remote Data Objects – RDO). Naime, RDO obezbeđuje jednostavan model
objekta sličan DAO modelu koji je dizajniran specijalno za pristup ODBC izvorima podataka. U
suštini, RDO predstavlja tanak omotač preko ODBC API.
OLE DB
Još jedan veliki zemljotres u svetu tehnologija pristupa podacima izazvalo je izdanje OLE DB-a.
Po strukturi, OLE DB liči na ODBC: komunikacija sa izvorom podataka vrši se preko OLE DB
dobavljača (sličan konceptu ODBC upravljačkih programa), koji su dizajnirani za svaki podržani
tip izvora podataka ponaosob. Naime, OLE DB dobavljači implementiraju skup COM interfejsa
koji dozvoljavaju pristup podacima u standardnom formatu red/kolona. Aplikacija koja koristi
pomenute podatke poznata je pod nazivom OLE DB korisnik (engl. OLE DB consumer). Kao što
ovi standardni dobavljači podataka izvode podatke iz izvora podataka i čine ih dostupnim kroz
OLE DB interfejse, tako i OLE DB sadrži određeni broj dobavljača usluga. Ovim se formira
''srednji niz'' OLE DB arhitekture, obezbeđujući usluge koje se upotrebljavaju sa dobavljačem
podataka. U pomenute usluge spadaju i udruživanje veza, registrovanje transakcija (sposobnost
da se automatski registruju MTS/COM komponente u okviru MTS/COM transakcije),
postojanost podataka, klijentsku manipulaciju podacima (Client Cursor Engine ili CCE),
hijerarhijske skupove zapisa (oblikovanje podataka) i pravljenje podataka na udaljenoj mašini.
Međutim, stvarna inovacija koja se krila iza koncepta OLE DB bila je Microsoftova strategija za
univerzalni pristup podacima (engl. Universal Data Access – UDA). Naime, ideja koja se nalazi iza
pomenutog koncepta UDA jeste da se podaci skladište na mnogim mestima – e-pošta, Excel
tabelarni proračun, Web stranice itd. – kao uostalom i u tradicionalnim bazama podataka, pa bi
stoga trebalo da smo u mogućnosti da programski pristupimo svim pomenutim podacima, i to
kroz jednu unifikovanu tehnologiju pristupa podacima. Upravo OLE DB predstavlja osnovu za
Microsoftovu implementaciju ove strategije. Broj OLE DB dobavljača postepeno se povećavao
da bi se pokrili kako sistemi relacionih baza podataka (čak i MySQL baza podataka poseduje
OLE DB dobavljač), tako i nerelacioni izvori podataka poput Exchange 2000Web Store,
datoteke Project 2000 i IIS virtuelni direktorijumi. Međutim, Microsoft je pre pojave ovih
dobavljača obezbedio široki spektar podrške za OLE DB – OLE DB dobavljač za ODBC
upravljačke programe. Stoga je od samog početka bilo jasno da se OLE DB mogao koristiti za
pristup bilo kom izvoru podataka koji sadrži ODBC upravljački program. Uostalom, pomenuta
taktika prihvaćena je i u ADO.NET-u.
ADO
ActiveX Data Objects (ADO) predstavlja tehnologiju koja je svoj naziv pozajmila programu
ADO.NET (iako su razlike između pomenutih tehnologija prilično velike). Naime, ADO je samo
jedan od OLE DB korisnika – tanak sloj koji omogućava korisnicima jezika visokog nivoa poput
VB-a i skript jezika da pristupe OLE DB izvorima podataka kroz jednostavan model objekta;
ADO je za OLE DB skoro isto što je i RDO bio za ODBC. Popularnost ADO-a leži u činjenici da
je omogućio velikom broju projektanata Visual Basica, ASP-a i Visual J++ jednostavan pristup
podacima na različitim lokacijama. Ako je OLE DB bio osnova na kojoj je izgrađen UDA, ADO
je bio odora u kojoj se on predstavljao većini projektanata. ADO i dalje predstavlja ispravan izbor
za projektante koji rade u .NET razvojnom okruženju. Samim tim što je većina klasa i koncepata
veoma slična, poznavanje ADO-a predstavlja veliku prednost pri učenju ADO.NET-a. U ovom
poglavlju ćemo se pozabaviti detaljnim upoređivanjem ADO i ADO.NET-a.
A sada ćemo proučiti karakteristike ADO.NET-a.
14
Pristup podacima i .NET okruženje
Uvod u ADO.NET
Iako smo ADO.NET predstavili kao neku vrstu neizbežnosti koja prati razvoj .NET okruženja i
pojavu novog pristupa podacima API, i dalje nam preostaje da objasnimo razlog. Uostalom,
sasvim je moguće nastaviti sa upotrebom ADO-a u .NET aplikacijama kroz COM
interoperabilnost. Međutim, postoje opravdani razlozi zašto ADO nije predviđen za novo
programsko okruženje. Stoga ćemo na brzinu pogledati zašto je korišćenje ADO.NET-a
efikasnije od pozivanja ADO-a iz .NET okruženja, pre nego što započnemo detaljno istraživanje
arhitekture ADO.NET-a.
Međujezička podrška
Treba znati da ADO nije dizajniran za međujezičku upotrebu. Naime, ciljni korisnici ovog
programa bili su VB programeri. Kao rezultat, ADO koristi veliki broj opcionih parametara
metoda koje podržavaju VB i VB.NET, ali ne i C jezici poput C#. Stoga, ukoliko koristite ADO
iz jezika C#, biće potrebno da specifikujete sve parametre u pozivima metoda; na primer, ako
pozovete metod Connection.Open, a pritom ne želite da specifikujete opcije, potrebno je da
unesete i parametar adConnectUnspecified. Iz priloženog se može videti da ADO
programiranje u .NET okruženju oduzima prilično vremena.
Jednostavnija arhitektura
Kao što smo napomenuli, ADO predstavlja samo tanak sloj preko OLE DB-a. Samim tim, ADO
građa postaje nezgrapnija dodavanjem slojeva između aplikacija i izvora podataka. Iako će veliki
broj ADO.NET kodova i dalje koristiti OLE DB, ovaj broj će se sve više smanjivati pojavom
originalnih .NET dobavljača podataka. Naime, tamo gde postoje originalni dobavljači,
ADO.NET radi mnogo brže od ADO-a, iz razloga što dobavljači komuniciraju direktno sa
izvorom podataka. U sledećem odeljku sledi detaljnije razmatranje ADO.NET arhitekture.
XML podrška
Jedna od glavnih karakteristika .NET razvojnog okruženja jeste podrška za XML. XML
predstavlja standardni i perzistentni format kroz .NET razvojno okruženje. Iako je ADO imao
određenu podršku za XML počev od verzije 2.1 pa nadalje, ona je bila prilično ograničena i
zahtevala je da XML dokumenta budu u tačno određenom formatu. Kratak pregled ADO.NET
podrške za XML možete pronaći u nastavku ovog poglavlja, dok detaljnije proučavanje sledi u
poglavlju 8.
15
Poglavlje 1
Veza Izvor
podataka
Komanda
DataReader
DataAdapter
16
Pristup podacima i .NET okruženje
Klase povezivanja
Klase povezivanja (engl. connection classes) veoma su slične objektu ADO Connection i koriste
se za predstavljanje veze sa specifičnim izvorom podataka. Klase povezivanja skladište
informacije koje su potrebne ADO.NET-u za povezivanje sa izvorom podataka u obliku
poznatog niza povezivanja (kao i u programu ADO). Svojstvo ConnectionString interfejsa
IDbConnection sadrži informacije poput korisničkog imena i lozinke korisnika, naziv i
lokaciju izvora podataka sa kojim se povezuje itd. Klase povezivanja takođe sadrže metode za
otvaranje i zatvaranje veza, kao i za početak transakcija i, na kraju, svojstva za podešavanja
perioda za vremensku kontrolu veze i vraćanja veze u prvobitno stanje (otvoreno ili zatvoreno).
U odeljku o postojećim .NET dobavljačima govorićemo o načinu na koji možete otvoriti veze
sa specifičnim izvorima podataka.
Klase komandi
Klase komandi izlažu interfejs IDbCommand i slične su ADO objektu Command. Upotrebljavaju
se za izvršavanje SQL iskaza ili sačuvanih procedura u izvoru podataka. Klase komandi, kao i
ADO objekat Command, takođe poseduju svojstvo CommandText koje sadrži tekst komande
koju je potrebno izvršiti u odnosu na izvor podataka, kao i svojstvo CommandType koje ukazuje
na to da li je komanda SQL iskaz, naziv sačuvane procedure ili naziv tabele. Postoje tri zasebna
izvršna metoda – ExecuteReader koji vraća objekat DataReader, zatim metod
ExecuteScalar koji vraća određenu vrednost i, na kraju, metod ExecuteNonQuery koji se
upotrebljava kada se podaci ne vraćaju kao odgovor upitu (na primer, za iskaz SQL UPDATE).
Klase komandi poseduju i kolekciju Parameters – kolekcija objekata koja predstavlja
parametre koje je potrebno proslediti u sačuvanu proceduru. Pomenuti objekti izlažu interfejs
IDataParameter i formiraju deo .NET dobavljača. Naime, svaki dobavljač poseduje zasebnu
implementaciju interfejsa IDataParameter (i IDataParamterCollection):
Parametar Sql:
Parametar IData
17
Poglavlje 1
DataReader
Komponenta DataReader predstavlja odgovor ADO.NET-a na povezani skup zapisa (engl.
recordset) u programu ADO. Međutim, DataReader je samo za prosleđivanje i čitanje (engl.
forward-only, read-only) – ne postoji mogućnost njegove upotrebe za ažuriranje izvora podataka.
Samim tim nam je omogućen ekstremno brz pristup podacima koje želimo da ponovimo samo
jednom, te je stoga preporučljiva upotreba objekta DataReader (umesto objekta DataSet)
gde god je to moguće. Naime, objekat DataReader može biti vraćen samo iz poziva metodu
ExecuteReader određenog komandnog objekta; ne postoji mogućnost direktnog formiranja
objekta. Upravo zbog ovoga je potrebno eksplicitno formiranje komandnog objekta, za razliku
od principa koji važi u programu ADO, gde je moguće pozvati objekat RecordSet bez
eksplicitnog stvaranja objekta Command. Samim tim, ADO.NET model objekta je
transparentniji od ''linearne'' hijerarhije programa ADO.
DataAdapter
Poslednja komponenta .NET dobavljača podataka je DataAdapter. Objekat DataAdapter
ponaša se kao most između nepovezanog objekta DataSet i izvora podataka. Zahvaljujući tome
ova komponenta otkriva dva interfejsa: IDataAdapter koji definiše metode za popularisanje
objekta DataSet sa podacima iz izvora podataka, kao i za ažuriranje izvora podataka sa
promenama objekta DataSet koje su obavljene u klijentu. Drugi pomenuti interfejs,
IDbDataAdapter definiše četiri svojstva tipa IDbCommand. Svako od pomenutih svojstava
podešava ili vraća komandni objekat koji specifikuje koju je komandu potrebno izvršiti kada se
postavi upit izvoru podataka ili kada se isti ažurira:
SqlDataAdapter:
IDataAdapter,
IDbDataAdapter
SelectCommand SqlCommand:
IDbCommand
UpdateCommand SqlCommand:
IDbCommand
DeleteCommand SqlCommand:
IDbCommand
18
Pristup podacima i .NET okruženje
SqlClient dobavljač
Dobavljač SqlClient predstavlja sastavni deo paketa ADO.NET i nalazi se u imenovanom
prostoru System.Data.SqlClient. Pomenuti dobavljač može se koristiti za pristup bazama
podataka SQL Server 7.0 (kao i kasnije verzije) ili, pak, za pristup bazama podataka MSDE.
Međutim, SqlClient dobavljač se ne može upotrebljavati sa SQL Server 6.5 ili prethodnim
verzijama baza podataka, te je stoga potrebno koristiti OleDb. NET dobavljač sa OLE DB
dobavljačem za SQL Server (SQLOLEDB) kada želite da pristupite ranijoj verziji SQL Servera.
Ako ste u mogućnosti da upotrebite SqlClient dobavljač, preporučujemo da to i uradite zato
što se korišćenjem OleDb dobavljača dodaje još jedan sloj vašem kodu pristupa podacima i
koristi COM interoperabilnost (OLE DB je zasnovan na COM-u).
Sve klase koje se nalaze u okviru dobavljača SqlClient počinju sa ''Sql'', pa zato možemo
reći da je klasa povezivanja SqlConnection, komandna klasa SqlCommand itd. Sada ćemo
pregledati ADO.NET kôd i otvoriti vezu sa pubs bazom podataka na SQl Serveru. Kao i kôd
većine kodova u ovom poglavlju (zapravo, u celoj knjizi), koristićemo C#:
Direktiva using koja se nalazi u prvom redu nije obavezna, ali ako je upotrebite, nećete morati
da kucate dodatne redove. U slučaju da je ne upotrebite, morali biste da napišete
System.Data.SqlClient.SqlConnection umesto jednostavnije varijante
SqlConnection. Primetićete da pri kodiranju u C# nije potrebno dodavanje reference
datoteci System.Data.dll (gde se nalaze dobavljači SqlClient i OleDb), čak i kada se
upotrebljava kompajler sa komandnom linijom. Međutim, kada su u pitanju drugi jezici,
potrebno je da dodate reference, osim u slučaju kada koristite Visual Studio.NET (program
automatski dodaje referencu).
Naš sledeći zadatak je da formiramo objekat SqlConnection – SqlClient implementacija
interfejsa IDbConnection. Prosledićemo informacije veze u konstruktor za pomenuti objekat
iako možemo da formiramo objekat upotrebom podrazumevanog (bez parametara)
konstruktora, a zatim podesimo njegovo svojstvo ConnectionString. Niz veze je skoro
identičan ADO nizu veze – jedina razlika je u tome što, u ADO.NET-u, ne moramo da
specifikujemo dobavljača koji koristimo. To smo već uradili formiranjem SqlConnection
objekta (umesto OleDbConnection objekta). Na kraju, pozivamo metod Open kako bismo
otvorili vezu. Za razliku od metoda Open, objekta ADO Connection, nismo u mogućnosti da
prosledimo niz veze kao parametar u pomenuti metod, pa zato moramo specifikovati
informacije veze pre samog njenog otvaranja.
19
Poglavlje 1
OleDb dobavljač
Ako ne koristite SQL Server 7.0 ili neku od ostalih verzija, naša preporuka je da koristite OleDb
dobavljač. Međutim, postoji nekoliko izuzetaka; ako vaš izvor podataka sadrži ODBC upravljački
program, ali ne i OLE DB dobavljač, potrebno je da upotrebite Odbc.NET dobavljač. Podrška za
MSDASQL (OLE DB dobavljač za ODBC upravljački program) je povučena iz OleDb dobavljača
negde između Beta 1 i Beta 2 verzije .NET razvojnog okruženja i, samim tim, ne postoji
odgovarajuća alternativa za ovu vrstu podrške. Ovo je urađeno da bi se sprečila upotreba ODBC
naziva izvora podataka (engl. Data Source Names) – DSN – zajedno sa ADO.NET-om, osim u
slučajevima gde je ODBC zaista neophodan. Čak i u programu ADO, upotreba DSN-a
podrazumevala je određeno smanjenje kvaliteta performansi (pogotovo u slučaju kada je OLE
DB dobavljač bio dostupan). Međutim, dodatni sloj ne bi se tolerisao u okvirima .NET okruženja.
Pomislite na datu arhitekturu: ADO.NET – COM interoperabilnost – (opcionalno) OLE DB
usluge – OLE DB dobavljač – ODBC upravljački program – izvor podataka!
Već smo pominjali sledeću situaciju u kojoj OleDb dobavljač nije od velike pomoći. Ako je
potrebno da pristupite izvoru podataka koristeći Exchange 2000 ili Internet Publishing Provider
(IPP), moramo vas obavestiti da ne postoji alternativa za COM interoperabilnost i zastareli
program ADO. Naime, OleDb dobavljač ne podržava interfejse IRecord i IStream koje
koriste pomenuti dobavljači.
OleDb dobavljač se po mnogim karakteristikama ponaša kao i tradicionalni ADO. Naime, on
predstavlja samo .NET omotač oko OLE DB-a (osim što su sada Ole Db dobavljači usluga
prilično zastareli, s obzirom na to da se pomenuta funkcija nalazi u programu ADO.NET). Osim
što moramo specifikovati da ćemo upotrebiti OleDb.NET dobavljač (formiranjem objekta
OleDbConnection), takođe je potrebno da specifikujemo OLE DB dobavljača podataka koji
želimo da koristimo pri uspostavljanju veze iz OLE DB-a sa izvorom podataka. Ovaj proces se
može obaviti na isti način kao i u programu ADO – uključivanjem svojstva Provider u niz
veze ili podešavanjem svojstva Provider objekta OleDbConnection.
OleDb dobavljač nalazi se u datoteci System.Data.dll (kao i SqlClient) i sadržan je u
.NET razvojnom okruženju. Klase koje sačinjavaju dobavljača nalaze se u imenovanom prostoru
System.Data.OleDb i sve imaju prefiks ''OleDb'' (OleDbConnection, OleDbCommand
itd.) Sledeće je prikazivanje pomenutog procesa, i to otvaranjem veze sa Access bazom
podataka Northwind (u ovom slučaju, Nwind.mdb):
Znak @ koji se nalazi ispred niza veze koristi se u programu C# kako bi se ukazalo na ''doslovan'' niz,
što znači da će svi iskočni znaci biti ignorisani. Ova opcija je veoma korisna kada su u pitanju putanje
datoteka (za izbegavanje znaka obrnuta kosa crta).
Ovaj primer se ne razlikuje mnogo od prethodnog, osim što je, kao što smo napomenuli,
potrebno da uključimo i svojstvo Provider u niz veze. Stoga, iako smo upotrebili različite
objekte, u suštini smo promenili samo tri stvari:
❐ direktivu using na početku koda;
❐ niz veze;
❐ prefiks ''OleDb'' svaki put kada formiramo objekte specifične za dobavljača.
Ovo je takođe prirodan izbor dobavljača koji se upotrebljava za povezivanje sa Oracle bazom
podataka:
20
Pristup podacima i .NET okruženje
using System.Data.OleDb;
OleDbConnection cn = new OleDbConnection("Provider=MSDAORA;" +
"Data Source=orcl.julian_new.wrox.com;User ID=scott;" +
"Password=tiger");
cn.Open();
Kao i u programu ADO, i ovde prosleđujemo naziv Oracle dobavljača OLE DB (MSDAORA),
naziv servisa (ovde je orcl.julian_new.wrox.com) kao izvor podataka, a zatim i šemu u
Oracle bazi podataka kao UserID (u ovom slučaju, scott).
Odbc dobavljač
Za razliku od ostala dva .NET dobavljača, Odbc dobavljač nije sadržan u .NET razvojnom
okruženju. Trenutnu beta verziju možete preuzeti kao .exe datoteku od 503 KB sa MSDN Web
lokacije http://www.microsoft.com/downloads/release.asp?ReleaseID=31125. Kada prenesete
pomenutu datoteku, aktivirajte je da biste instalirali klase (ovaj program će instalirati skup u
globalnu keš memoriju skupa (engl. Global Assembly Cache) tako da će klase automatski biti
globalno dostupne na lokalnoj mašini. Međutim, potrebno je da vašim projektima dodate i
referencu za skup (System.Data.Odbc.dll) kako biste koristili dobavljač.
Odbc dobavljač bi trebalo upotrebljavati svaki put kada vam je potreban pristup izvoru
podataka bez OLE DB dobavljača (poput PostgreSQL ili starijih baza podataka kao što su
Paradox ili dBase) ili u slučaju kada želite da upotrebite ODBC upravljački program za funkciju
koja nije dostupna u OLE DB dobavljaču. Odbc dobavljač je po strukturi veoma sličan OleDb
dobavljaču – ponaša se kao .NET omotač oko ODBC API i pritom dozvoljava programu
ADO.NET da pristupi izvoru podataka kroz ODBC upravljački program.
Klase ODBC dobavljača nalaze se u imenovanom prostoru System.Data.Odbc i počinju
prefiksom ''Odbc''. U primeru koji sledi povezaćemo se sa bazom podataka MySQL na sledeći
način (ovde se povezujemo sa kopijom Access baze podataka Northwind koju smo uvezli u
bazu podataka MySQL):
Jedina razlika u odnosu na prethodni primer je u tome što ovde upotrebljavamo ODBC niz veze
umesto OLE DB niza veze (kao što bismo uradili pri povezivanju sa ODBC izvorom podataka iz
programa ADO). Shodno tome, ovo može biti prethodno konfigurisana veza u obliku DSN-a
(Data Source Name) ili može biti potpuni niz veze (kao u prethodnom primeru) koja specifikuje
ODBC upravljački program koji se upotrebljava, naziv servera baze podataka i bazu podataka
na serveru, kao i korisnički ID (UID) i lozinku (PWD).
Komponenta DataSet
Još jedna u nizu važnih komponenti ADO.NET-a jeste DataSet. Pomenuta komponenta u suštini
odgovara skupu zapisa (engl. recordset) programa ADO, ali se ipak razlikuje na dva veoma bitna
načina. Naime, objekat DataSet je uvek isključen, a posledica toga je da ne proverava odakle
dolaze podaci. Objekat DataSet može se koristiti na potpuno isti način za manipulisanje
podacima iz tradicionalnog izvora podataka ili iz XML dokumenta. Da bismo povezali objekat
DataSet sa izvorom podataka, potrebno je da upotrebimo objekat DataAdapter kao
posrednika između DataSet i .NET dobavljača podataka:
21
Poglavlje 1
Veza Izvor
podataka
Komanda
DataReader
DataSet DataAdapter
XML
dokument
// Otvori vezu
OleDbConnection cn = new OleDbConnection(
@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\NWind.mdb");
cn.Open();
// Popuni DataSet
da.Fill(ds, "Employees");
22
Pristup podacima i .NET okruženje
Klasa DataTable
Ovaj poslednji parametar nam ukazuje na jednu od najbitnijih razlika između objekta DataSet
i ADO skupa zapisa, a to je da objekat DataSet može sadržati nekoliko tabela podataka. Iako
je nešto slično postojalo u programu ADO u okviru opcije uređivanja podataka, ipak je objekat
DataSet učinio korak više – njegove tabele mogu biti uzete iz različitih izvora podataka.
Takođe, rešen je problem vezan za upotrebu užasne sintakse SHAPE. ADO.NET poseduje klasu
DataTable koja predstavlja jednu tabelu u okviru objekta DataSet. Objekat DataSet sadrži
svojstvo Tables koje vraća kolekciju pomenutih objekata (DataTableCollection). Klasa
DataTable prikazuje podatke u uobičajenom tabelarnom formatu i poseduje kolekciju
objekata DataColumn i DataRow koje predstavljaju svaku kolonu i svaki red u tabeli:
DataSet
DataTableCollection
DataTable
DataColumnCollection DataColumn
DataRowCollection DataRow
Iako klasa DataColumn odgovara ADO objektu Field, program ADO nije posedovao
objekat koji je prikazivao jedan red podataka, te stoga s pravom možemo reći da klasa DataRow
predstavlja veliku prednost!
Ako želite da pristupite podacima u klasi DataTable, potrebno je da prvo pristupite
odgovarajućem objektu DataRow, a zatim i indeksirate objekat kako biste dobili podatke za
željenu kolonu. Indeks može biti numerički indeks kolone (0 za prvu kolonu itd.) ili naziv
kolone. U sledećem primeru ponovićemo pregledanje kolekcije DataColumnCollection
kako bismo izdvojili nazive kolone u prvoj tabeli objekta DataSet. Zatim ćemo ponoviti
izvršavanje iskaza u svakom redu i svakoj koloni za trenutni red i prikazati podatke u prostoj
tabeli komandne linije:
23
Poglavlje 1
Ako ste izvršili pomenuti deo kôda upotrebom objekta DataSet koji smo prethodno
popularisali, videćete sledeći prikaz na ekranu:
// Prikaži UpdateCommand
Console.WriteLine(cmdBuilder.GetUpdateCommand().CommandText);
24
Pristup podacima i .NET okruženje
da.Update(ds.Tables[0]);
// Zatvori vezu
cn.Close();
Složićete se da je prethodni proces prilično jasan. Prosledili smo naš objekat DataAdapter u
konstruktor OleDbCommandBuilder, čime je došlo do automatskog povezivanja sa našim
izvorom podataka. Takođe smo izbegli grešku InvalidOperationException formiranjem
primerka CommandBuilder za objekat DataAdapter, čime su automatski izgrađene
komande. Ako želimo da izdvojimo tekst generisanih komandi, to možemo učiniti pozivanjem
CommandBuilder metoda GetUpdateCommand, GetInsertCommand itd. S obzirom na to
da ažuriramo samo zapis (umesto brisanja ili ubacivanja zapisa), prikazaćemo jedino komandu
UPDATE. Da bismo obavili prethodno pomenuti proces, potrebno je da pozovemo metodu
GetUpdateCommand koja vraća komandni objekat (u našem slučaju, objekat OleDbCommand
iz razloga što koristimo OleDb dobavljač). Shodno tome, CommandText će glasiti ovako:
UPDATE 'Employees' SET 'FirstName' = ? , 'LastName' = ? WHERE (
'EmployeeID' = ? AND 'FirstName' = ? AND 'LastName' = ? )
Sada možemo da pozovemo DataAdapter metod Update. U ovom procesu postoji problem
preopterećivanja, te se stoga objekat DataSet može uzeti kao parametar (sa ili bez naziva
tabele u okviru objekta DataSet), kao, uostalom i klasa DataTable ili pak niz objekata
DataRow. Naime, ovde samo prosleđujemo klasu DataTable koju želimo da ažuriramo. Na
kraju zatvaramo vezu.
ADO.NET i XML
Jedna od najimpresivnijih novih karakteristika ADO.NET-a jeste ugrađena podrška za XML.
Naime, XML sada predstavlja standardni postojani format za ADO.NET DataSets. Iako smo
bili u mogućnosti da sačuvamo skupove zapisa u XML formatu počev od verzije 2.1 programa
ADO, podrazumevani format i dalje je bio format Advanced Data TableGram (ADTG), a XML
podrška i dalje ograničena. Na primer, nismo mogli da učitamo proizvoljan XML dokument u
ADO skup zapisa jer je dokument morao da bude u tačno određenom formatu.
XML podrška u ADO.NET-u je mnogo kompletnija. XML predstavlja apsolutno integralni deo
ADO.NET-a, a ne samo jednostavan programski dodatak. XML je format koji se koristi za
serijalizovanje i transportovanje objekata DataSets. Serijalizacija objekta DataSet kao XML
dokumenta (u datoteku, niz ili objekat TextWriter) predstavlja prilično trivijalan proces:
25
Poglavlje 1
<EmployeeID>2</EmployeeID>
<FirstName>Andrew</FirstName>
<LastName>Fuller</LastName>
</Employees>
<!-- and so on... -->
</NewDataSet>
Takođe smo u mogućnosti da učitamo dobro formiran XML dokument u objekat DataSet bez
potrebe korišćenja prethodno definisanih struktura (iako postoji mogućnost da izgubimo sadržaj
ako struktura dokumenta nije tabelarna). Na primer (potrebno je da dodate System.IO;
direktivu da biste pokrenuli svoj kôd za ovaj primer):
Ovde smo napravili veoma jednostavan XML dokument i uskladištili ga u nizu. Upotrebićemo
DataSet metod ReadXml za učitavanje XML dokumenta u objekat DataSet. Ovde se XML
dokument u obliku niza ne prihvata kao parametar, ali se zato prihvata klasa StringReader
(ova klasa nalazi se u imenovanom prostoru System.IO), te stoga pravimo novu klasu
StringReader iz našeg niza i prosleđujemo je metodu ReadXml. Na kraju ćemo prikazati
objekat DataSet u tabelarnom formatu.
Kada izvršite ovaj proces, trebalo bi da vidite sledeće:
26
Pristup podacima i .NET okruženje
Definisani DataSets
S obzirom na to da se XML može pronaći u svim delovima .NET razvojnog okruženja, postoji
čitav niz alatki koje su dostupne za rad sa XML dokumentima i šemama. Najimpresivnija među
njima jeste xsd.exe koja može da preuzme XML šemu za definisanje šema (skr. XSD) kao
ulazni podatak i iz nje generiše strogo definisani tip objekta DataSet. Nije potrebno naglasiti da
postoji mogućnost upotrebe objekta DataSet za automatsko generisanje XSD šema.
Na primer, u mogućnosti smo da generišemo XSD šemu za tabelu Employees u bazi podataka
Northwind, i to upotrebom sledećeg koda:
xsd Employees.xsd /d
Ovaj proces generiše datoteku C# pod nazivom Employees.cs koja definiše klasu
NewDataSet izvedenu iz DataSet zajedno sa strogo definisanim tipom klasa DataTable i
DataRow. S obzirom na to da je klasa NewDataSet izvedena iz DataSet, ona poseduje
funkciju normalne klase DataSet. Međutim, klasa DataRow izlaže svaku kolonu u redu kao
svojstvo odgovarajućeg tipa podataka (na primer, kolona varchar biće izložena u obliku niza).
Da biste videli klasu DataSet u akciji, potrebno je da kompajlirate sledeću C# datoteku u DLL:
27
Poglavlje 1
Sigurno smatrate da je ovo beznačajna razlika i da nije vredna truda oko generisanja nove klase.
Ako koristite Notepad, u potpunosti ste u pravu. Međutim, ako koristite moćni IDE sa modulom
IntelliSense i automatsko upotpunjenje poput programa Visual Studio .NET, nazivi kolona biće
prikazani kao svojstva reda:
Drugim rečima, zaboravite na greške zbog nepravilno otkucanog ili pogrešno zapamćenog
naziva kolone u bazi podataka! Još jedna prednost je u tome što je poboljšana čitljivost kôda i
smanjena mogućnost greške jer se strogo definišu tipovi u vreme kompajliranja. Mogućnost
unošenja vrednosti pogrešnog tipa u kolonu svedena je na minimum.
28
Pristup podacima i .NET okruženje
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Set cn = CreateObject("ADODB.Connection")
cn.Open "Provider=SQLOLEDB;Data Source=JULIAN;Initial Catalog=pubs;" & _
"User ID=sa;Password="
Set rs = CreateObject("ADODB.Recordset")
rs.LockType = adLockBatchOptimistic ' Specify the lock type
rs.CursorLocation = adUseClient ' Specify that we're using
' OLE DB's Client Cursor Engine
rs.CursorType = adOpenStatic ' Specify the cursor type
rs.Open "SELECT * FROM authors", objConn ' Open the recordset
Set objRec.ActiveConnection = Nothing ' Disconnect the recordset
objConn.Close ' Close the connection
Set objConn = Nothing
Svaki put kada u ADO.NET-u napravite klasu DataSet, ona će automatski biti isključena.
Uostalom, videli smo da je potrebno upotrebiti klasu DataAdapter kao posrednika između
DataSet i dobavljača podataka. Na primer:
OleDbConnection cn = new
OleDbConnection(@"Provider=Microsoft.Jet.OLEDB.4.0;
Data Source=C:\NWind.mdb");
cn.Open();
OleDbDataAdapter da = new OleDbDataAdapter("SELECT * FROM Employees", cn);
DataSet ds = new DataSet();
da.Fill(ds, "Employees");
cn.Close();
Ovaj pristup je mnogo transparentniji i manje podložan greškama, a ceo proces je mnogo kraći.
Samim tim nije potrebno da definišemo dodatnu informaciju poput CursorType zato što je
isključeni DataSet po definiciji statički. (Takođe ćemo dobiti statički kursor u programu ADO,
nezavisno od tipa koji smo definisali, pre svega zbog toga što Client Cursor Engine [CCE]
podržava samo statičke kursore. Stoga ne možemo definisati tip kursora za DataSet.)
29
Poglavlje 1
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
rs.Close
cn.Close
OleDbConnection cn = new
OleDbConnection(@"Provider=Microsoft.Jet.OLEDB.4.0;
Data Source=C:\NWind.mdb");
cn.Open();
OleDbCommand cmd = new OleDbCommand("SELECT * FROM Employees", cn);
OleDbDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
while (dr.Read())
{
Console.WriteLine (dr["FirstName"] + " " + dr["LastName"]);
}
dr.Close();
Primetićete da specifikovanje kursora ili tipova blokade nije potrebno. Već znamo da nam je
potreban kursor samo za prosleđivanje i samo za čitanje, te stoga nema potrebe da pamtimo
veliki broj parametara pri otvaranju klase DataReader.
Još jedna od prednosti je u tome što metod Read automatski prelazi u sledeći red. U programu
ADO bilo je lako napisati kôd koji bi stvarao beskonačnu petlju, i to samo zbog toga što bismo
zaboravili da dodamo poziv metodu MoveNext. Međutim, sada je situacija potpuno drugačija –
DataReader.Read pomera pokazivač unutrašnjeg reda klase DataReader za jedan red čime
podaci tog reda postaju dostupni. Sam metod vraća Bulovu vrednost „tačno” dok su podaci i
dalje u procesu čitanja, a vrednost „netačno” kada stigne do kraja datoteke. Stoga, umesto da
zasebno pozivamo metod MoveNext i EOF, to možemo učiniti odjednom. Rezultat – nema
beskonačnih petlji!
Jedino treba zapamtiti da klasa DataReader polazi od početne lokacije datoteke, te je stoga
potrebno pozvati metod Read najmanje jednom pre nego što nam se omogući pristup podacima.
30
Pristup podacima i .NET okruženje
Suština svih navedenih promena je sledeća: tamo gde smo imali jedan objekat (RecordSet)
koji je obavljao sav posao u ADO 2.6, sada imamo specijalizovane klase za dve najčešće
situacije. Zato možemo poništiti veliki broj nejasnih (i često nepravilno protumačenih)
parametara koje smo imali pri otvaranju skupa zapisa ili izvršavanju komande, a da pritom
budemo sigurni u to da dobijamo tačno određeni i željeni tip objekta. Međutim, u slučaju da
želimo nestandardan način pristupa našim podacima – na primer, povezani skup rezultata kojim
možemo da upravljamo i koji možemo da ažuriramo – nećemo moći da se oslonimo na ovaj
program. Naime, ADO.NET ne obezbeđuje ovakvu vrstu podrške.
Takođe je važno zapamtiti da je celokupno .NET razvojno okruženje izrađeno tako što je pažnja
bila podjednako podeljena između raspodeljene obrade, preko Interneta i izlaganja funkcija
putem Web servisa. Međutim, ako ostavite otvorene veze sa bazom podataka, postoji velika
mogućnost da će to ozbiljno uticati na podesivost aplikacije, što se kosi sa prvenstvenim ciljem
.NET okruženja, a to je, upravo, sprečavanje takvih pojava. Ako vam je zaista potrebna
pomenuta funkcija, preporučujemo vam upotrebu klasične verzije programa ADO.
Naime, i dalje ste u mogućnosti da ažurirate izvor podataka, i to izvršavanjem komandi upotrebom
komandnih klasa. Ako vam je potreban povezani pristup, kombinovanje pomenutih klasa sa klasom
DataReader predstavlja najefikasniju tehniku. Međutim, takođe će vam biti potreban namenski
kôd za simuliranje originalnog povezanog skupa zapisa koji se može ažurirati.
CoInitialize(NULL);
CoCreateInstance(CLSID_MSDASQL, NULL, CLSCTX_INPROC_SERVER,
IID_IDBInitialize,
(void **) &pIDBInitialize);
31
Poglavlje 1
// Methods
System.Data.IDbTransaction BeginTransaction();
System.Data.IDbTransaction BeginTransaction(
System.Data.IsolationLevel il);
void ChangeDatabase(string databaseName);
void Close();
System.Data.IDbCommand CreateCommand();
void Open();
} // end of System.Data.IDbConnection
Sada ćemo videti kako se prethodno navedeni proces implementira pomoću objekta
OleDbConnection. Da bi se uštedeo prostor, neki od članova su izostavljeni iz sledeće
definicije. Svi članovi koji su definisani putem interfejsa IDbConnection takođe su i
implementirani; označeni članovi predstavljaju članove koji nisu implementacije članova
IDbConnection:
public sealed class System.Data.OleDb.OleDbConnection :
System.ComponentModel.Component,
System.ComponentModel.IComponent,
IDisposable,
ICloneable,
System.Data.IDbConnection
{
// Properties
public string ConnectionString { virtual get; virtual set; }
public int ConnectionTimeout { virtual get; }
public string Database { virtual get; }
public string DataSource { get; }
public string Provider { get; }
public string ServerVersion { get; }
public ConnectionState State { virtual get; }
// Events
public event OleDbInfoMessageEventHandler InfoMessage;
public event StateChangeEventHandler StateChange;
// Methods
public System.Data.OleDb.OleDbTransaction BeginTransaction();
public System.Data.OleDb.OleDbTransaction
BeginTransaction(System.Data.IsolationLevel isolationLevel);
public virtual void ChangeDatabase(string value);
public virtual void Close();
public System.Data.OleDb.OleDbCommand CreateCommand();
public virtual System.Runtime.Remoting.ObjRef CreateObjRef(Type
requestedType);
public System.Data.DataTable GetOleDbSchemaTable(Guid schema, object[]
32
Pristup podacima i .NET okruženje
restrictions);
public virtual void Open();
public static void ReleaseObjectPool();
} // end of System.Data.OleDb.OleDbConnection
33
Poglavlje 1
Ovde smo formirali objekat veze kao i obično (uostalom, veza će uvek biti specifična za
dobavljača), a zatim smo ga rasporedili u interfejs IDbConnection. Zatim smo u mogućnosti
da pozovemo metode veze kao što je definisano u interfejsu. Na primer, metod
CreateCommand vraća instancu interfejsa IDbCommand umesto instancu klase
OleDbCommand. S obzirom na to da svi dobavljači moraju da podrže pomenute interfejse, ova
tehnika nam omogućava da pišemo kodove koji su u potpunosti nezavisni od dobavljača (osim
polazne veze). Međutim, interfejsi ne obezbeđuju implementacije sopstvenih članova, pa će zato
biti upotrebljene implementacije koje su specifične za dobavljače. Na primer, kada pozovemo
metod IDbCommand.ExecuteReader, metod ExecuteReader klase OleDbCommand će i
dalje biti izvršen.
Da bismo koristili ADO 2.x iz .NET okruženja, potrebno je da napravimo Runtime Callable
Wrappers (RCW) za COM komponente. Ovo možemo obaviti u Visual Studio .NET-u, i to
izborom ADODB biblioteke sa kartice COM u okviru za dijalog Add Reference:
34
Pristup podacima i .NET okruženje
Kao alternativa javlja se i mogućnost upotrebe alatke komandne linije TlbImp.exe za uvoz
biblioteke tipa u .NET okruženje:
Primetićete da se ovim ne instalira skup u globalnu keš memoriju skupa (engl. Global Assembly
Cache), te je stoga potrebno da proverimo da li je DLL u istom direktorijumu kao i kôd koji ga
poziva.
Upotreba RCW za ADODB biblioteku slična je njegovoj upotrebi iz VB 6. Međutim, stavka na
koju je potrebno obratiti pažnju ako pišete C# kôd jeste da C# ne podržava opcione parametre
za pozive metoda, pa je zato potrebno uključiti sve parametre. Ovim se pozivi metoda prilično
komplikuju, te nije na odmet imati pri ruci referencu za ADO model objekta.
35
Poglavlje 1
Korišćenje ADO.NET-a
Kao što smo prethodno napomenuli, jedna od najvažnijih funkcija .NET razvojnog okruženja
jeste podrška za više jezika. Iako većina kodova u ovoj knjizi koristi jezik C# , ADO.NET je
podjednako jednostavan za korišćenje iz bilo kog .NET jezika. Da bismo vam olakšali korišćenje
ADO.NET-a, objasnićemo vam kako se piše ADO.NET kôd u svim Microsoft .NET jezicima.
Za ove primere, otvorićemo vezu sa pubs bazom podataka u SQl Serveru, izdvojiti podatke iz
tabele authors u DataReader, a zatim ćemo ponoviti izvršavanje svih iskaza i prikazati polja
au_fname i au_lname za svaki red.
Primer C#
S obzirom na to da je većina primera u ovoj knjizi u jeziku C#, počećemo objašnjenjem ovog
jezika. Do sada smo videli većinu ovih kodova – kôd za otvaranje veze sa SQL serverom
identičan je kodu koji smo videli u odeljku o SqlClinet dobavljaču, dok je kôd za ponavljanje
izvršavanja iskaza u dobavljaču skoro isti kao i primer koji smo upotrebili za upoređivanje
povezanog pristupa u programima ADO i ADO.NET:
using System;
using System.Data.SqlClient;
class CSharpAdoExample
{
static void Main(string[] args)
{
// Napravi objekat SqlConnection i otvori vezu
SqlConnection cn = new SqlConnection(
"Data Source=JULIANS2;Initial Catalog=pubs;User ID=sa;Password=");
cn.Open();
36
Pristup podacima i .NET okruženje
Imports System
Imports System.Data.SqlClient
Module VBAdoExample
Sub Main()
End Module
Zapamtite da ukoliko kompajlirate VB.NET datoteke koje sadrže ADO.NET kôd sa komandne
linije, potrebno je da dodate reference za skupove System.dll i System.Data.dll. Na primer:
Primer JScript.Neta
JScript.NET predstavlja najjednostavniji jezik. Sintaksa je skoro identična sintaksi u verziji C#,
osim što je JScript.NET, prema podrazumevanim vrednostima, labavo definisanih tipova (stoga
se svi ADO.NET objekti deklarišu kao vars). Takođe, u JScript.NET-u nije potrebno uključiti
kodove aplikativnog nivoa u okviru klase ili bilo koji tip funkcije Main (ovo se generiše putem
JScript kompajlera):
import System;
import System.Data.SqlClient;
37
Poglavlje 1
38
Pristup podacima i .NET okruženje
Primer J#
Sintaksa u jeziku Java veoma je slična onoj u jeziku C#, pa je sledeći primer sličan primeru iz
jezika C#:
import System.*;
import System.Data.*;
import System.Data.SqlClient.*;
Interesantna stvar vezana za jezik J# jeste mogućnost upotrebe kako tradicionalnih Java paketa,
tako i .NET imenovanih prostora (oba se uvoze upotrebom ključne reči import). Na primer, u
prethodno navedenom kodu, upotrebili smo tradicionalni Java metod System.out.println
za štampanje na konzoli, ali smo isto tako mogli da upotrebimo i .NET metodu
System.Console.WriteLine. Naravno, podrazumeva se da je ADO.NET kôd uvek .NET
specifičan.
39
Poglavlje 1
ADO.NET događaji
Pre nego što završimo ovo poglavlje, predstavićemo vam još jednu karakteristiku ADO.NET-a –
ADO.NET događaj. ADO.NET događaji su veoma slični ADO događajima. Događaji se
generišu kada se nešto značajno dogodi, poput otvaranja ili zatvaranja veze. Kao i u programu
ADO, događaji se izlažu kao članovi ADO.NET objekata i naš kôd može informisati objekat da
želimo biti obavešteni kada se određeni događaj desi. Upravo se tada izvršava specijalno
određeni metod poznat kao modul za upravljanje događajima (engl. event handler).
Iako su događaji u ADO.NET-u pojmovno slični ADO događajima, nažalost, način
implementiranja modula za upravljanje događajima se prilično razlikuje. Da stvar bude još
komplikovanija, način implementiranja se razlikuje u zavisnosti od jezika koji koristite.
Međutim, generalna procedura je ista. Kao prvo, potrebna nam je referenca za objekat koji će
generisati događaje. Zatim, moramo da informišemo objekat o tome da želimo biti obavešteni
kada se određeni događaj desi. Konačno, potrebno je da napišemo modul za rukovanje
događajima koji će biti pozvan svaki put kada se podigne događaj za taj objekat.
Sada ćemo razmotriti na koji način sve ovo funkcioniše u C# i ADO.NET-u. Kao primer
upotrebićemo događaj StateChange klase OleDbConnection koji se generiše svaki put
kada se veza otvori ili zatvori. Naime, događaji u .NET-u koriste specijalnu kategoriju tipa
podataka poznatu kao delegat (engl. delegate). Delegat predstavlja referencu za metod – u ovom
slučaju, za naš metod rukovanja događajem. Da bismo dobijali obaveštenja o događaju,
potrebno je da dodamo pomenuti delegat našem događaju StateChange.
U jeziku C# pomenuti proces obavlja se jednostavnom upotrebom operatora +=. Referencu za
delegat dobijamo tako što ćemo napraviti novi objekat odgovarajućeg tipa modula za rukovanje
događajima (u ovom slučaju, objekat StateChangeEventHandler) i proslediti našu funkciju
u konstruktor:
// kôd C#
cn.StateChange += new StateChangeEventHandler(cn_StateChange);
Sledeće što je potrebno uraditi jeste napisati metod za rukovanje događajima. U ovom slučaju,
napisaćemo novo stanje u konzoli. Moduli za rukovanje događajima poseduju predodređene
potpise i naš metod se mora povinovati ovom pravilu. Uvek postoje dva parametra – objekat
koji je podigao događaj i objekat koji sadrži dodatne argumente. Tip ovog objekta varira u
zavisnosti od tipa modula za rukovanje događajima. Za događaj StateChange, objekat je tipa
StateChangeEventArgs.
Sledi kôd C# za modul za rukovanje događajima:
40
Pristup podacima i .NET okruženje
Primetićete da je pošiljalac prosleđen u metod kao tip object, pa je stoga potrebno da izvršimo
njegovu konverziju u stvarni tip pošiljaoca (u ovom slučaju, OleDbConnection) pre samog
pristupanja njegovim metodima i svojstvima.
Jer, ako ne uključimo opciju OptionStrict, VB.NET neće zahtevati pomenutu konverziju tipova,
pa će kôd biti jednostavniji:
Da bismo videli kako sve ovo funkcioniše, sledi kompletan pregled kôda C#. VB.NET kôd
možete preuzeti sa Wroxove Web lokacije.
using System;
using System.Data;
using System.Data.OleDb;
class AdoEventsExample
{
public static void Main()
{
// Formiraj objekat OleDbConnection
OleDbConnection cn = new OleDbConnection(
@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\NWind.mdb");
41
Poglavlje 1
Rezime
Iako ovo poglavlje nije previše obimno, uspeli smo da obradimo veliki deo materije. Međutim,
tek smo zagrebali po površini onoga što ADO.NET može da pruži. Nadamo se da smo vam
pokazali dovoljno da vas ohrabrimo da nastavite sa proučavanjem ovog programa. Sledi brza
rekapitulacija tema koje smo obradili:
❐ Kratak pregled glavnih karakteristika .NET razvojnog okruženja.
❐ Glavni pravci razvoja tehnologija pristupa podacima u proteklih nekoliko godina i
način na koji se ADO.NET uklapa u pomenuti ubrzani razvoj.
❐ Tri .NET dobavljača podataka, njihove osnovne komponente i objekat DataSet.
❐ XML podrška ugrađena u ADO.NET.
❐ Na koji se način ADO.NET razlikuje od ADO 2.6.
❐ ADO.NET događaji.
42