Kod netipiziranih DataSetova koriste se klase DataSet, DataTable, DataColumn i DataRow. Ove klase sadrže kolekcije koje vraćaju standardne objekte nezavisno od tipa podataka u DataSet-u. Npr. Columns kolekcija DataRow objekta uvek vraća objekte tipa DataColumn nezavisno od tipa podataka u tim kolonama. Kolekcija Tables objekta klase DataSet uvek prikazuje objekte tipa DataTable nezavisno od toga koja se tabela koristi. Standardna DataSet klasa koja je ugrađene u .NET biblioteku predstavlja netipizirani DataSet. Visual Studio 2008 omogućava kreiranje i tzv. tipiziranih DataSetova. Tipizirani DataSetovi su klase koje su izvedene iz klase DataSet , i sadrže svojstva i metode koje omogućavaju pristup sadržajima unutar DataSeta na tipski bezbedan način (type-safe). Struktura tipskog DataSeta se predstavlja XML šemom, tj. fajlom koji ima xsd ekstenziju.
Na slici je prikazan prozor Add New Item koji se otvara desnim klikom na ikonicu projekta u Solution Exploreru. Od ponuđenih šablona treba odabrati Add New DataSet čime se otvara DataSet dizajner. Potrebno je definisati ime DataSetu pri čemu je ekstenzija xsd.
Vidimo prikazan prozor DataSet dizajner koji omogućava da se u dizajn modu kreira tipizirani DataSet. DataSet dizajner ima sopstvenu paletu alatki.
Prevlačenjem TableAdapter kontrole na površinu dizajnera pokreće se TableAdapter Configuration wizard. U prvom prozoru ovog wizarda se bira konekcija na bazu podataka sa kojom će DataAdapter da radi. Ukoliko željena konekcija ne postoji u ComboBox kontroli, može se kreirati nova klikom na dugme New Connection. U primeru na slici uspostavlja se konekcija sa bazom Adwenture Works. Klikom na dugme Next posle definisnja konekcije na bazu podataka prelazi se na sledeći korak wizarda.
U ovom koraku wizarda treba definisati kako TableAdapter pristupa podacima iz baze, pri čemu se može izabrati opcija da se definiše sql komanda, da se kreira nova uskladištena procedura, ili da se koristi postojeća uskladištena procedura.U primeru na slici izborom opcije Use SQL Statements odabrali smo da definišemo SQL komandu na osnovu koje će TableAdapter da pristupa podacima iz baze. Klikom na dugme Next prelazi se na sledeći korak wizarda.
U ovom koraku wizarda treba definisati SELECT komandu TableAdaptera. Komanda se može uneti ručno u prikazanoj tekst oblasti ili se može definisati grafički klikom na dugme Query Builder...
Klikom na dugme Query Builder otvara se najpre prozor Add Table koji omogućava da se odaberu tabele nad kojima će biti pisan upit. U primeru na slici odabrana je tabela ProductCategory. Tabela biva prikazana unutar prozora Query Buildera. Sada se čekiraju potrebne kolone ove tabele čime se grafički kreira SELECT upit nad ovom tabelom.
Klikom na dugme Advanced Options otvara se istoimeni prozor. Ukoliko je SQL upit definisan nad jednom tabelom baze podataka u prozoru Advanced Options se nudi mogućnost da se na osnovu SELECT komande TableAdaptera automatski generišu INSERT, UPDATE i DELETE komanda.
U ovom prozoru wizarda treba definisati koje metode wizard treba da generiše. Postoji mogućnost generisanja tzv. Fill metode kojoj treba proslediti tabelu kao parametar da bi je napunila podacima iz baze. Drugi tip metode je GetData koja vraća tabelu napunjenu podacima na osnovu definisane SELECT komande TableAdaptera.
U posledenjem koraku wizarda korisniku se prikazuje obaveštenje šta je korišćenjem wizarda generisano.
Ukoliko se odlučimo prilikom pokretanja TableAdapter Configuration wizarda da SELECT komanda TableAdaptera predstavlja neku od postojećih uskladištenih procedura dobija se prozor kao na slici. U ovom prozoru treba odabrati neku od postojećih uskladištenih procedura.
Pokretanjem TableAdapter Configuration wizarda u DataSet se dodaje odgovarajuća tabela i njoj pridruženi TableAdapter. Ista procedura se ponavlja za svaku od tabela koju želimo da dodamo u DataSet. Ukoliko želimo da kreiramo povezane tabele unutar DataSet-a , kao što su povezane u samoj bazi onda to radimo na način koji je prikazan na slici. Desnim tasterom kliknemo na tabelu i odaberemo opciju Add Relation.
Sada se otvara Relation prozor u kome treba definisati tabele koje se povezuju kao i atribute na osnovu kojih se vrši povezivanje tabela. Treba odabrati roditeljsku tabelu i definisati njen primarni ključ. Takođe, treba definisati i child tabelu i definisati strani ključ u toj tabeli. Takođe u ovom prozoru se mogu definisati i akcije referencijalnog integriteta, tj. šta se dešava sa child vrstama kada se briše ili ažurira njima odgovarajuća parent vrsta. Ukoliko su tabele povezane u bazi podataka, automatski će biti povezane i u DataSet-u.
Na slici je prikazan DataSet sa definisanim tabelam i definisanim vezama između tabela.
Tabela se u DataSet može ubaciti i njenim prevlačenjem iz Server Explorera. Prethodno je potrebno da se u Server Exploreru klikom na dugme Connect to Database uspostavi konekcija sa bazom podataka. Prevlačenjem tabele na površinu DataSet dizajnera u DataSetu se kreira tabela i u njoj odgovarajući TableAdapter ali nije moguće detaljnije konfigurisati SELECT komandu TableAdaptera. Prevlačenjem dve tabele koje su povezane u bazi podataka, vrši se njihovo automatsko povezivanje i u DataSetu.
Izborom stavki menija Data ->Add New DataSource pokreće se DataSource Configuration wizard koji služi za kreiranje DataSeta. Potrebno je odabrati tabele koje će ući u sastav DataSeta.
Na slici je prikazan primer kreiranog DataSeta nakon izbora tabela u DataSource Configuration wizardu. Takođe, kao i za slučaj prevlačenja tabela iz server explorera, nije moguće detaljno konfigurisati select naredbe pojedinih TableAdaptera.
Prikažimo ClassView prozor u Visual Studiu, ukoliko on nije prikazan. U ovom prozoru vide se klase koje su kreirane nakon konfigurisanja DataSeta. Kao što se sa slike može videti kreira se tipizirani DataSet kao i tipizirane DataTable klase, pa čak i klase koje predstavljaju vrste u pojedinim tipiziranim tabelama.
private NorthwindDataSet nDS = new NorthwindDataSet(); public Form2() { InitializeComponent(); } private void Form2_Load(object sender, EventArgs e) { CategoriesTableAdapter cta = new CategoriesTableAdapter(); ProductsTableAdapter pta = new ProductsTableAdapter(); cta.Fill(nDS.Categories); pta.Fill(nDS.Products); listBox1.DataSource = nDS.Categories; listBox1.DisplayMember = nDS.Categories.CategoryNameColumn.ColumnName; } |
U prikazanom kodu vrši se instanciranje tipiziranog data seta NorthwindDataSet. U Load proceduri forme instanciraju se tipizirani TableAdapteri koji rade sa tabelama Categories i Products. Zatim se pozivom Fill metode odgovarajućeg tipiziranog DataSeta vrši punjenje podacima odgovarajućeg tipizitanog DataTable objekta. Podaci iz tabele Categories se koriste za punjenje ListBox kontrole.
private void listBox1_SelectedIndexChanged(object sender, EventArgs e) { listBox2.Items.Clear(); DataRowView drv = (DataRowView) listBox1.SelectedItem; NorthwindDataSet.CategoriesRow kategorija = (NorthwindDataSet.CategoriesRow)drv.Row; NorthwindDataSet.ProductsRow[] proizvodi = kategorija.GetProductsRows(); foreach (NorthwindDataSet.ProductsRow proizvod in proizvodi) { listBox2.Items.Add(proizvod.ProductName); } } |
Na osnovu selektovane stavke u ListBox kontroli koja je povezana sa tabelom Categories iz DataSet kreira se DataRowView objekat koji predstavlja pogled na odgovarajući DataRow objekat tj. vrstu iz tabele Categories. Zatim se kastovanjem kreira odgovarajući CategoriesRow objekat koji predstavlja tipizirani DataRow objekat. Svaki CategoriesRow objekat ima metodu GetProductsRows koja je kreirana automatski na osnovu postojanja veze između tabela Categories i Products. Pozivom metode GetProductsRows objekta CategoriesRow kreira se niz ProductsRow objekata koji odgovaraju datom CategoriesRow objektu. Primetimo da se klasama CategoriesRow i ProductsRow pristupa posredstvom NorthwindDataSet klase.