PROGRAMSKI PREVODIOCI 10. ČAS ŠK 2019-20 DOC. DR … · PROGRAMSKI PREVODIOCI 10. ČAS ŠK...

Preview:

Citation preview

PROGRAMSKI PREVODIOCI 10. ČAS

ŠK 2019-20

DOC. DR LJUBICA KAZI

Zadatak: Data je desktop aplikacija za naručivanje robe (data u okviru 7. časa vežbi). Dodati

biblioteku klasa koja će se zvati KlasePodataka i koja će realizovati sve CRUD (unos, brisanje, izmena,

preuzimanje podataka) operacije, tako što će preuzeti iz postojećeg rešenja (sa korisničkog interfejsa)

deo koda koji radi sa SQL upitima i pozivima biblioteke klasa SQLDBUtils. Na ovaj način će korisnički

interfejs biti rasterećen detalja implementacije koji se odnose na rad sa bazom podataka.

IZGLED KORISNIČKOG INTERFEJSA DESKTOP APLIKACIJE:

Trenutna struktura pre refaktorisanja:

Ciljna struktura aplikacije nakon refaktorisanja:

Postupak realizacije:

1. Kreiranje novog projekta, tipa Class Library. Zove se Klase podataka.

2. U novom projektu kreiraćemo 3 klase. Prva klasa ima samo attribute koji su bitni za narucivanje

i kreiramo set i get metode primenom opcije menija Refactor-Encapsulate field. Selektujemo

atribut I biramo opciju Encapsulate field.

Kreiran je public property:

Možemo podesiti tipove podataka u skladu sa bazom podataka:

Pošto je ID auto increment u bazi podataka, bitna polja su sva ostala.

Konstruktor najčešće sadrži inicijalizaciju promenljivih.

Trebalo bi da svaka klasa ispod naziva ima kratak opis namene – jedna klasa treba da ima samo jednu

namenu. Metode te klase menjaju njena stanja, tj. vrednosti privatnih metoda koja čuvaju stanja.

namespace KlasePodataka { public class clsNarucivanje { // NAMENA: Klasa ciji objekat koja odgovara jednom zapisu iz baze podataka, ima samo set-get metode // atributi private string _KorisnikIme; private string _KorisnikAdresa; private string _Proizvod; private int _Kolicina; private int _Cena; private DateTime _DatumIsporuke; // konstruktor public clsNarucivanje() { // inicijalizacija atributa _KorisnikIme=""; _KorisnikAdresa=""; _Proizvod=""; _Kolicina=0; _Cena=0; _DatumIsporuke=DateTime.Now; } // public public string KorisnikIme { get { return _KorisnikIme; } set { _KorisnikIme = value; } } public string KorisnikAdresa { get { return _KorisnikAdresa; } set { _KorisnikAdresa = value; } } public string Proizvod { get { return _Proizvod; } set { _Proizvod = value; } } public int Kolicina { get { return _Kolicina; } set { _Kolicina = value; } } public int Cena { get { return _Cena; } set { _Cena = value; } } public DateTime DatumIsporuke { get { return _DatumIsporuke; } set { _DatumIsporuke = value; } } } }

3. Druga klasa je tipizirana lista osnovnih objekata clsNarucivanje.

Kreiramo novu klasu (Project, Add Class).

Dobijamo novu klasu, pa moramo dodati modifikator pristupa public, jer ako nije napisano,

podrazumeva se private.

public class clsNarucivanjeLista { // NAMENA: Tipizirana lista objekata klase clsNarucivanje, sa svim CRUD operacijama nad listom // atributi private List<clsNarucivanje> pListaNarucivanja; // property public List<clsNarucivanje> ListaNarucivanja { get { return pListaNarucivanja; } set { if (this.pListaNarucivanja != value) this.pListaNarucivanja = value; } } // konstruktor public clsNarucivanjeLista()

{ pListaNarucivanja = new List<clsNarucivanje>(); } // privatne metode // javne metode public void DodajElementListe(clsNarucivanje objNoviNastavnik) { pListaNarucivanja.Add(objNoviNastavnik); } public void ObrisiElementListe(clsNarucivanje objNastavnikZaBrisanje) { pListaNarucivanja.Remove(objNastavnikZaBrisanje); } public void ObrisiElementNaPoziciji(int pozicija) { pListaNarucivanja.RemoveAt(pozicija); } public void IzmeniElementListe(clsNarucivanje objStariNastavnik, clsNarucivanje objNoviNastavnik) { int indexStarogNastavnika = 0; indexStarogNastavnika = pListaNarucivanja.IndexOf(objNoviNastavnik); pListaNarucivanja.RemoveAt(indexStarogNastavnika); pListaNarucivanja.Insert(indexStarogNastavnika, objNoviNastavnik); } }

4. Dodajemo treću klasu NarucivanjeDB, koja služi za rad sa bazom podataka. Dodajemo

REFERENCES, ADD REFERENCE - biblioteku klasa SQLDBUtils.dll koja je univerzalna biblioteka

koja radi sa MS SQL Server bazom podataka.

Dodavanje dll fajla u reference:

Prikazan je na spisku referenci:

Da bismo mogli da koristimo, dodajemo using SQLDBUtils:

Klasa NarucivanjeDB:

public class clsNarucivanjeDB { // atributi private clsSqlKonekcija objSqlKonekcija; private clsSqlTabela objSqlTabela; private DataSet dsNarucivanje; // konstruktor public clsNarucivanjeDB(string MSSQLInstanca, string NazivBazePodataka) { objSqlKonekcija = new clsSqlKonekcija("DESKTOP-U5822NP\\MSSQL2008", "", "PP2020_Narucivanje"); objSqlKonekcija.OtvoriKonekciju(); objSqlTabela = new clsSqlTabela(objSqlKonekcija, "Narudzba"); dsNarucivanje = new DataSet(); } // privatne metode // javne metode public DataSet DajSveNarudzbe() { // dsNarucivanje je globalna promenljiva na nivou ove forme i dobija vrednost ovde dsNarucivanje = objSqlTabela.DajPodatke("Select * from Narudzba"); return dsNarucivanje;

} public DataSet DajNarudzbePremaRobi(string robaFilter) { // dsNarucivanje je globalna promenljiva na nivou ove forme i dobija vrednost ovde dsNarucivanje = objSqlTabela.DajPodatke("Select * from Narudzba where Proizvod='" + robaFilter + "'"); return dsNarucivanje; // nema potrebe da bude return, jer se salje vrednost u globalnu promenljivu koja je vidljiva svuda } public void SnimiNovuNarudzbu(clsNarucivanje objNovaNarudzba, out bool Uspeh, out string tekstGreske) { // 1. transformacija ulazne vrednosti string strDatumIsporuke = objNovaNarudzba.DatumIsporuke.Month.ToString() + "/" + objNovaNarudzba.DatumIsporuke.Day.ToString() + "/" + objNovaNarudzba.DatumIsporuke.Year.ToString(); // 2. priprema SQL upita tipa insert string sqlInsertUpit = "INSERT INTO Narudzba VALUES('" + objNovaNarudzba.KorisnikIme + "', '" + objNovaNarudzba.KorisnikAdresa + "','" + objNovaNarudzba.Proizvod + "'," + objNovaNarudzba.Kolicina + "," + objNovaNarudzba.Cena + ",'" + strDatumIsporuke + "')"; // 3. izvrsavanje SQL upita tipa insert try { Uspeh = objSqlTabela.IzvrsiAzuriranje(sqlInsertUpit); tekstGreske=""; } catch (Exception greska) { Uspeh = false; tekstGreske = greska.Message; } } }

5. Izmene u korisničkom interfejsu – izbacujemo (remove) SQLDBUtils i dodajemo samo biblioteku

KlasePodataka.dll. Menjamo i u okviru using.

Menjamo programski kod u korisničkom interfejsu tako da se koriste samo klase iz KlasePodataka.dll

biblioteke:

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; // using KlasePodataka; namespace DesktopApp_KorisnickiInterfejs { public partial class frmNarucivanje : Form { // atributi private clsNarucivanje objNarucivanje; private clsNarucivanjeLista objNarucivanjeLista; private clsNarucivanjeDB objNarucivanjeDB; private DataSet dsNarucivanje; // METODE // konstruktor public frmNarucivanje() { InitializeComponent(); } // nase metode private void NapuniGrid(DataSet dsPodaciZaGrid) { dgvSpisakRobe.DataSource = dsPodaciZaGrid.Tables[0]; dgvSpisakRobe.Refresh(); } private void IsprazniKontrole() { txbKorisnikIme.Text = ""; txbKorisnikAdresa.Text= ""; txbProizvod.Text= ""; txbKolicina.Text= ""; txbCena.Text = ""; } // dogadjaji private void frmNarucivanje_Load(object sender, EventArgs e) { // inicijalizacija globalnih promenljivih na nivou stranice objNarucivanje = new clsNarucivanje(); objNarucivanjeLista = new clsNarucivanjeLista(); objNarucivanjeDB = new clsNarucivanjeDB("DESKTOP-U5822NP\\MSSQL2008", "PP2020_Narucivanje"); } private void btnSvi_Click(object sender, EventArgs e) { txbFilterNazivRobe.Text = ""; NapuniGrid(objNarucivanjeDB.DajSveNarudzbe()); } private void btnFilter_Click(object sender, EventArgs e) { if (txbFilterNazivRobe.Text.Equals("")) { MessageBox.Show("Niste uneli kriterijum filtriranja!"); txbFilterNazivRobe.Focus(); return; } else { NapuniGrid(objNarucivanjeDB.DajNarudzbePremaRobi(txbFilterNazivRobe.Text)); } } private void btnSnimi_Click(object sender, EventArgs e) { // 1. provera popunjenosti if (txbKorisnikIme.Text.Equals("")) { MessageBox.Show("Niste uneli ime korisnika!"); txbKorisnikIme.Focus(); return;

} if (txbKorisnikAdresa.Text.Equals("")) { MessageBox.Show("Niste uneli adresu korisnika!"); txbKorisnikAdresa.Focus(); return; } if (txbProizvod.Text.Equals("")) { MessageBox.Show("Niste uneli proizvod!"); txbProizvod.Focus(); return; } if (txbKolicina.Text.Equals("izaberite")) { MessageBox.Show("Niste uneli kolicinu!"); txbKolicina.Focus(); return; } if (txbCena.Text.Equals("")) { MessageBox.Show("Niste uneli cenu!"); txbCena.Focus(); return; } // provera ispravnosti podataka // TO DO // ****************snimanje podataka // 2.preuzimanje podataka sa KI u atribute objekta klase clsNarucivanje objNarucivanje.KorisnikIme =txbKorisnikIme.Text; objNarucivanje.KorisnikAdresa = txbKorisnikAdresa.Text; objNarucivanje.Proizvod = txbProizvod.Text; objNarucivanje.Kolicina = int.Parse(txbKolicina.Text); // type casting - izmena stringa u tip int objNarucivanje.Cena =int.Parse (txbCena.Text); // type casting - izmena stringa u tip int objNarucivanje.DatumIsporuke = dtpDatumIsporuke.Value; // direktno je tipa date, pa moze biti dodeljeno //3. izvrsavanje snimanja bool uspeh = false; string porukaGreske = ""; objNarucivanjeDB.SnimiNovuNarudzbu(objNarucivanje, out uspeh, out porukaGreske); // 4. poruka uspesnosti i ostale aktivnosti if (uspeh) { MessageBox.Show("USPESNO SNIMLJENI PODACI!"); NapuniGrid(objNarucivanjeDB.DajSveNarudzbe()); IsprazniKontrole(); } else { MessageBox.Show("Greska snimanja novog zapisa:" + porukaGreske); } } private void btnOdustani_Click(object sender, EventArgs e) { IsprazniKontrole(); } private void btnExportXML_Click(object sender, EventArgs e) { dsNarucivanje.WriteXml("SpisakNarudzbi.XML"); MessageBox.Show("Uspesno snimljen spisak narudzbi u XML!"); } } }

Aplikacija nakon ovih izmena funkcioniše kao i ranije, samo je drugačije implementirana.

Refaktorisanje na ovaj način je završeno. Naravno, ista aplikacija se može uraditi na još nekoliko

načina, a da ima isto ponašanje.

Dalje refaktorisanje, jedan od načina - mogla bi se iskoristiti lista objekata za punjenje combo boxa, a

da se ne koristi dataset.