Univerzitet u Novom Sadu Tehnički fakultet »MihajloPupin ... · dat spisak fajlova koji čine...
Transcript of Univerzitet u Novom Sadu Tehnički fakultet »MihajloPupin ... · dat spisak fajlova koji čine...
-
Univerzitet u Novom Sadu
Tehnički fakultet
»MihajloPupin«
Zrenjanin
SEMINARSKI RAD
Predmet: Programski prevodioci
Tema: Kreiranje objektno-orjentisane C# desktop aplikacije uz samostalno kreiranje
biblioteke klasa i analiza ispravnosti programskog koda primenom Visual Studio
NET okruţenja
- Evidencija naručivanja robe - (TIP 2)
Predmetni nastavnik: Doc. Dr. Ljubica Kazi Primer kreirao: predmetni nastavnik
Zrenjanin, 2020. godina
-
__________________________________________________________ 1
Sadrţaj:
1. ZADATAK
2. OPIS POSLOVNOG KONTEKSTA REALIZOVANOG PRIMERA
3. KRATAK OPIS INTEGRISANOG RAZVOJNOG OKRUŢENJA
3.1. Namena alata 3.2. Izgled ekrana alata
3.3. Opis načina korišćenja
4. KORISNIČKO UPUTSTVO RAZVIJENE APLIKACIJE
4.1. Namena aplikacije
4.2. Ekrani i način korišćenja
5. KLJUČNI ELEMENTI IMPLEMENTACIJE 5.1. SQL skript
5.2. Ključni delovi programskog koda sa objašnjenjem
6. GREŠKE PROGRAMSKOG KODA
6.1. Segmenti programskog koda sa greškama
6.2. Opšti prikaz gramatički ispravnog programskog koda 6.3. EBNF prikaz ispravnih naredbi za segmente koda sa greškama
7. PRIKAZ PRIMENE ALATA U DETEKTOVANJU GREŠAKA
7.1. Ekranski prikaz izveštaja kompajlera nad neispravnim kodom
7.2. Ekranski prikaz reakcije na run-time greške
8. ZAKLJUČAK 9. LITERATURA
10. LISTING
-
__________________________________________________________ 2
1. ZADATAK
Kreirati desktop aplikaciju C# sa primenom gotove biblioteke SQL DB Utils. Kreirati biblioteku
KlasePodataka koja radi sa podacima iz baze podataka i primenjuje SQLDBUtils (rad sa jednom
tabelom iz baze podataka). Kreirati u kodu namerne greške 4 tipa – leksičku, sintaksnu,
semantičku i run-time. Pustiti kompajler da detektuje greške i prikazati izveštaj koji daje u vezi
grešaka i ispravnog rada.
2. OPIS POSLOVNOG KONTEKSTA REALIZOVANOG PRIMERA
U ovom primeru realizovana je jednostavna desktop aplikacija za naručivanje robe.
Omogućava unos i tabelarni prikaz sa filtriranjem, kao i eksport podataka u XML. Podaci o
naručivanju odnose se na korisnika koji naručuje robu, robu, kao i samu isporuku.
-
__________________________________________________________ 3
3. KRATAK OPIS RAZVOJNOG OKRUŢENJA
3.1. Microsoft Visual studio NET 2010 Ultimate Edition
3.1.1. Namena alata
Microsoft Visual studio NET 2010 Ultimate Edition je alat opšteg tipa koji predstavlja
integrisano razvojno okruţenje za kreiranje softvera opšteg tipa. Daje podršku za razvoj programa primenom različitih programskih jezika, pri čemu se najčešće koristi C#. TakoĎe,
daje mogućnosti kreiranja projekata različitih vrsta, koje se mogu kombinovati u različite
softverske arhitekture. Najčešće korišćene su desktop aplikacije, biblioteke klasa, veb servisi,
veb aplikacije, a novije verzije Visual Studio nude mogućnost i izrade mobilnih aplikacija.
3.1.2. Izgled ekrana alata
Na slici 1. je prikazan izgled alata Microsoft Visual studio NET 2010 Ultimate Edition nakon
učitavanja realizovane desktop aplikacije. U levom delu najčešće se nalazi Toolbox koji
omogućava postavljanje grafičkih kontrola, u gornjem desnom uglu je Solution Explorer gde je
dat spisak fajlova koji čine projekat, a dole desno je odeljak Properties gde se podešavaju osobine aktivne grafičke kontrole.
Slika 1. Izgled alata Microsoft Visual studio NET 2010 Ultimate Edition nakon učitavanja
projekta desktop aplikacije
3.1.3. Opis načina korišćenja
U ovom odeljku će biti opisan osnovni postupak rada u alatu.
-
__________________________________________________________ 4
U okviru ovog alata početni korak predstavlja izbor tipa projekta.
Slika 2. Izbor tipa projekta u Microsoft Visual studio NET 2010 Ultimate Edition
U realizaciji ovog seminarskog rada korišćena su 2 tipa projekta:
1. Windows –> Windows forms application – korisnički interfejs 2. Windows –> Class Library – biblioteka klasa.
Nakon grafičkog dizajna korisničkog interfejsa, postavlja se progamski kod vezan za odreĎene
dogaĎaje. U properties delu u okviru simbola „munje“ mogu se podesiti dogaĎaji, tj. kod koji će
se izvršiti kada se desi odreĎeni dogaĎaj, npr. klik.
Slika 3. Izbor opcije za podešavanje dogaĎaja nad grafičkim objektom
-
__________________________________________________________ 5
Da bi se kreirala biblioteka klasa, biramo projekat Class Library. Inicijalno dobijamo 1 klasu, a
da bismo dodali još klasa, biramo opciju Project, add class.
Da bismo mogli da koristimo mogućnosti biblioteka klasa, postoje standardne biblioteke koje su već prisutne u samom Visual Studiju, ali moţemo dodati i sami. (U solution exploreru,
References, desni klik, Add reference ili Project meni i opcija add reference – biramo DLL fajl da
bismo ga priključili projektu). Kada se doda referenca na DLL u solution exploreru, bitno je
napomenuti da prilikom korišćenja dodatnih klasa (standardnih ili samostalno kreiranih) treba
dodati u sekciji “using” navesti naziv biblioteke klasa. Tek tada će njegove klase biti prepoznate (Slika 4). Dodavanje biblioteka klasa moguće je unutar projekta tipa Class Library gde se
dodaju druge biblioteke klasa ili unutar drugih projekata, npr. desktop aplikacije I drugih.
Slika 4. Dodavanje biblioteke klasa SQLDBUtils u projekat u 2 koraka
– References i using
-
__________________________________________________________ 6
3.2. Microsoft SQL Server 2008 R2
3.2.1. Namena alata
Microsoft SQL Server 2008 R2 predstavlja alat za rad i sistem za upravljanje relacionim bazama
podataka. Kreira baze podataka sa ekstenzijom mdf. Daje mogućnost postavljanja upita I
upravljanja strukturom baze podataka, koja osim tabela I relacija moţe da sadrţi poglede,
stored procedure I sl. Pruţa mogućnost i grafičkog prikaza povezanosti tabela putem dijagrama.
3.2.2. Izgled ekrana alata
Osnovni ekran za rad sa MS SQL Server alatom prikazan je na slici 5.
Slika 5. Osnovni ekran za rad u MS SQL Server alatu
U levom delu nalazi se spisak baza podataka, a u okviru svake se listaju njegovi elementi.
Centralni deo je namenjen za prikaz detalja.
3.2.3. Opis načina korišćenja
Nakon pokretanja dobijamo početni ekran na kom su prikazani podaci o samoj SQL Server
instanci alata, tj. njegovom nazivu, koji se kasnije koristi u okviru stringa konekcije u
programu.
-
__________________________________________________________ 7
Nakon izbora opcije Connect dobijamo glavni ekran za rad.
Izborom odreĎene baze podataka mogu se izvršavati upiti. Ukoliko nije kreirana, pomoću
opcije New Query moţe se izvršiti upit tipa Create database, create table. Više upita se moţe izvršiti paketno, samo je bitno da iza svakog upita piše naredba GO.
Izborom opcije New Query dobijamo prostor za upis upita, koji se pokrecu na opciju Execute
(Slika 6).
Slika 6. Izvršavanje upita u alatu MS SQL Server
-
__________________________________________________________ 8
4. KORISNIČKO UPUTSTVO RAZVIJENE APLIKACIJE
4.1. Namena aplikacije i osnovne funkcije
Osnovna namena aplikacije je evidencija naručivanja robe. Osnovne funkcije su:
Unos podataka
Tabelarni prikaz
Filtriranje podataka Eksport trenutno prikazanih podataka iz tabelarnog prikaza u XML datoteku.
4.2. Ekrani i način korišćenja
Nakon pokretanja dobijamo osnovni ekran bez prikazanih podataka u tabeli. Nakon izbora
prikaz svih narudţbi, dobijamo sledeći ekran:
Nakon unosa podataka :
-
__________________________________________________________ 9
Izborom opcije SNIMI dobijamo poruku, a podaci se dopunjuju u tabelarnom prikazu.
Stanje nakon potvrde poruke:
-
__________________________________________________________ 10
Nakon izbora opcije za Eksport:
-
__________________________________________________________ 11
5. KLJUČNI ELEMENTI IMPLEMENTACIJE
5.1. SQL script
USE [master]
GO
CREATE DATABASE [PP2020_Narucivanje]
GO
USE [PP2020_Narucivanje]
GO
CREATE TABLE [dbo].[Narudzba](
[ID] [int] NOT NULL identity(1,1) PRIMARY KEY,
[KorisnikIme] [nvarchar](60) NOT NULL,
[KorisnikAdresa] [nvarchar](60) NOT NULL,
[Proizvod] [nvarchar](100) NOT NULL, [Kolicina] [int] NOT NULL,
[Cena] [int] NOT NULL,
[DatumIsporuke] [date] NOT NULL
)
GO
5.2. Ključni delovi programskog koda sa objašnjenjem
Uključivanje biblioteke klasa // using KlasePodataka;
Početni dogaĎaj koji se automatski izvršava na početku
private void frmNarucivanje_Load(object sender, EventArgs e) { // inicijalizacija globalnih promenljivih na nivou stranice dsNarucivanje = new DataSet(); objNarucivanje = new clsNarucivanje(); objNarucivanjeLista = new clsNarucivanjeLista(); objNarucivanjeDB = new clsNarucivanjeDB("DESKTOP-U5822NP\\MSSQL2008", "PP2020_Narucivanje"); }
Preuzimanje podataka sa korisničkog interfejsa:
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
-
__________________________________________________________ 12
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 Snimanje podataka objNarucivanjeDB.SnimiNovuNarudzbu(objNarucivanje, out uspeh, out porukaGreske);
Tabelarni prikaz:
private void NapuniGrid(DataSet dsPodaciZaGrid) { dgvSpisakRobe.DataSource = dsPodaciZaGrid.Tables[0]; dgvSpisakRobe.Refresh(); }
private void btnSvi_Click(object sender, EventArgs e) { txbFilterNazivRobe.Text = ""; // moramo ovako, da bi dsNarucivanje kao globalna promenljiva dobila vrednost zbog Exporta dsNarucivanje = objNarucivanjeDB.DajSveNarudzbe(); NapuniGrid(dsNarucivanje); }
Eksport podataka
Napomena: potrebno je da dsNarućivanje bude globalna promenljiva na nivou cele forme, da bi čuvala vrednost izmeĎu raznih dogaĎaja (snimi, svi, filter…).
Globalne promenljive su definisane na početku koda
namespace DesktopApp_KorisnickiInterfejs { public partial class frmNarucivanje : Form { // atributi private clsNarucivanje objNarucivanje; private clsNarucivanjeLista objNarucivanjeLista; private clsNarucivanjeDB objNarucivanjeDB; private DataSet dsNarucivanje;
…
Kod eksporta iz DataSet-a koji se puni na raznim dogaĎajima:
private void btnExportXML_Click(object sender, EventArgs e) { dsNarucivanje.WriteXml("SpisakNarudzbi.XML"); MessageBox.Show("Uspesno snimljen spisak narudzbi u XML!"); }
-
__________________________________________________________ 13
6. GREŠKE PROGRAMSKOG KODA
6.1. Segmenti programskog koda sa greškama i korekcija
SINTAKSNE GREŠKE
NEISPRAVNO objNarucivanje = new clsNarucivanje()
ISPRAVNO objNarucivanje = new clsNarucivanje();
NEISPRAVNO txbKolicina.Focus;
ISPRAVNO txbKolicina.Focus();
LEKSIČKE GREŠKE
NEISPRAVNO dgvSpisakRobe.DataSrc = dsPodaciZaGrid.Tables[0];
ISPRAVNO dgvSpisakRobe.DataSource = dsPodaciZaGrid.Tables[0];
SEMANTIČKE GREŠKE
NEISPRAVNO txbKorisnikIme.Text = 0;
ISPRAVNO txbKorisnikIme.Text = "";
NEISPRAVNO NapuniGrid(objNarucivanjeDB.DajNarudzbePremaRobi(txbFilterNazivRobe.Text), false);
ISPRAVNO NapuniGrid(objNarucivanjeDB.DajNarudzbePremaRobi(txbFilterNazivRobe.Text));
RUN TIME GREŠKE
U programskom kodu korisničkog interfejsa postavljeni su pogrešni podaci i to rezultuje “pucanjem programa” i Exception greškom koju je generisao DBMS:
//ISPRAVNO objNarucivanjeDB = new clsNarucivanjeDB("DESKTOP-U5822NP\\MSSQL2008", "PP2020_Narucivanje"); // ovo je neispravno na mom racunaru - jer je drugaciji naziv MS SQL Server instance: objNarucivanjeDB = new clsNarucivanjeDB("DESKTOP-U5822NP\\MSSQL2008AAA", "PP2020_Narucivanje");
Napomena: Ni u korisničkom interfejsu ni u bibliotekama klasa nije dobro postaviti fiksnu
vrednost, jer ona ulazi u EXE fajl. Kada se nešto promeni (npr. naziv računara, baze
-
__________________________________________________________ 14
podataka…) onda bi svaki put trebalo ulaziti I menjati. Zato se ovakvi podaci parametrizuju I
čuvaju u eksternim konfiguracionim datotekama, npr. XML.
U programskom kodu klase u biblioteci KlasePodataka, postavljena je fiksna putanja. Ovo trenutno ne generiše run time error, jer je podatak trenutno odgovarajući. Ipak, potrebno je
parametrizovati, tj. zaista koristiti parameter konstruktora, umesto fiksnih vrednosti.
NEISPRAVNO: public clsNarucivanjeDB(string MSSQLInstanca, string NazivBazePodataka) { // ovo nije dobro da bude u biblioteci klasa fiksno, generisace run-time gresku kada je na drugom racunaru // ili kada se promeni MS SQL Server instanca alata objSqlKonekcija = new clsSqlKonekcija("DESKTOP-U5822NP\\MSSQL2008", "", "PP2020_Narucivanje"); objSqlKonekcija.OtvoriKonekciju(); objSqlTabela = new clsSqlTabela(objSqlKonekcija, "Narudzba"); dsNarucivanje = new DataSet(); }
KORIGOVANO: public clsNarucivanjeDB(string MSSQLInstanca, string NazivBazePodataka) { objSqlKonekcija = new clsSqlKonekcija(MSSQLInstanca, "", NazivBazePodataka); objSqlKonekcija.OtvoriKonekciju(); objSqlTabela = new clsSqlTabela(objSqlKonekcija, "Narudzba"); dsNarucivanje = new DataSet(); }
6.2. Pravila i EBNF prikaz gramatički ispravnog programskog koda
PRAVILO: Naredba uvek ima ; na kraju.
EBNF: ::=”;”
PRAVILO: Procedura ima zagrade.
EBNF: namerno ostavljeno bez rešenja, jer studenti treba sami da reše.
PRAVILO: String promenljiva uvek dobija string vrednost.
EBNF: namerno ostavljeno bez rešenja
-
__________________________________________________________ 15
7. PRIKAZ PRIMENE ALATA U DETEKTOVANJU GREŠAKA
7.1. Ekranski prikaz izveštaja kompajlera nad neispravnim kodom i nakon popravke
Nakon pokretanja build opcije menija (Build->Build Solution), dobijamo izveštaj kompajlera u
okviru Error Liste, kao što je prikazano na narednoj slici.
Klikom na stavku sa Error Liste, pozicioniramo se na mesto ili pribliţno mesto greške.
TakoĎe, kompajler omogućuje da kod koji nije ispravan bude podvučen odreĎenom bojom.
Kada stanemo mišem iznad podvučenog koda, dobijamo opis greške.
-
__________________________________________________________ 16
Nakon svih popravki dobijamo Izveštaj: Errors = 0, Build succeeded.
-
__________________________________________________________ 17
7.2. Ekranski prikaz reakcije na run-time greške
7.2.1. Prvi primer run-time greške
Ova greška se aktivirala nakon izbora tastera za eksport podataka.
Razlog je što je dsNarucivanje nije instanciran na Form load dogaĎaju. Drugi problem je što
kasnije ne dobija vrednosti, jer je pisalo:
NapuniGrid(objNarucivanjeDB.DajSveNarudzbe());
dsNaručivanje je već bila globalna promenljiva: namespace DesktopApp_KorisnickiInterfejs { public partial class frmNarucivanje : Form { // atributi private DataSet dsNarucivanje;
Treba uraditi korekcije:
1. INSTANCIRANJE OBJEKTA, kao odgovor na gornju poruku da nije instancirano private void frmNarucivanje_Load(object sender, EventArgs e) { // inicijalizacija globalnih promenljivih na nivou stranice dsNarucivanje = new DataSet();
2. Dodeljivanje podataka na događajima, da bi se mogli koristiti za eksport.
dsNarucivanje = objNarucivanjeDB.DajNarudzbePremaRobi(txbFilterNazivRobe.Text);
-
__________________________________________________________ 18
NapuniGrid(dsNarucivanje);
… dsNarucivanje = objNarucivanjeDB.DajSveNarudzbe(); NapuniGrid(dsNarucivanje);
7.2.2. Drugi primer run-time greške
Namerno su izmenjeni podaci koji su potrebni za string konekcije. private void frmNarucivanje_Load(object sender, EventArgs e) { // inicijalizacija globalnih promenljivih na nivou stranice dsNarucivanje = new DataSet(); objNarucivanje = new clsNarucivanje(); objNarucivanjeLista = new clsNarucivanjeLista(); //ISPRAVNO objNarucivanjeDB = new clsNarucivanjeDB("DESKTOP-U5822NP\\MSSQL2008", "PP2020_Narucivanje"); // ovo je neispravno: objNarucivanjeDB = new clsNarucivanjeDB("DESKTOP-U5822NP\\MSSQL2008AAA", "PP2020_Narucivanje"); }
Nakon pokretanja, prikazan je osnovni ekran, ali nakon pokretanja tastera “Prikaţi sve
narudzbe” kada je pokušano konektovanje na bazu podataka, prikazana je ova greška.
-
__________________________________________________________ 19
8. ZAKLJUČAK
Cilj ovog rada je da se predstavi uputstvo za izradu seminarskog rada tipa 2. Ovaj primer pored same ilustracije elemenata seminarskog rada ima za cilj i da opiše sam način izrade
seminarskog rada u okviru Microsoft Visual Studio NET i Microsoft SQL Server alata. Poseban
naglasak je na objektno-orjentisanom programiranju.
S obzirom da je ovo primer seminarskog rada za predmet Programski prevodioci, poseban naglasak je na greškama koje prijavljuje kompajler.
9. LITERATURA
[1] Kompletna lista grešaka i upozorenja za C# programski jezik koje prijavljuje Visual Studio NET:
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/
[2] BNF I EBNF slajdovi
https://condor.depaul.edu/ichu/csc447/notes/wk3/BNF.pdf
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/https://condor.depaul.edu/ichu/csc447/notes/wk3/BNF.pdf
-
__________________________________________________________ 20
10. LISTING
10.1. Listing korisničkog interfejsa 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 dsNarucivanje = new DataSet(); objNarucivanje = new clsNarucivanje(); objNarucivanjeLista = new clsNarucivanjeLista(); objNarucivanjeDB = new clsNarucivanjeDB("DESKTOP-U5822NP\\MSSQL2008", "PP2020_Narucivanje"); } private void btnSvi_Click(object sender, EventArgs e) { txbFilterNazivRobe.Text = ""; // moramo ovako, da bi dsNarucivanje kao globalna promenljiva dobila vrednost zbog Exporta
-
__________________________________________________________ 21
dsNarucivanje = objNarucivanjeDB.DajSveNarudzbe(); NapuniGrid(dsNarucivanje); } private void btnFilter_Click(object sender, EventArgs e) { if (txbFilterNazivRobe.Text.Equals("")) { MessageBox.Show("Niste uneli kriterijum filtriranja!"); txbFilterNazivRobe.Focus(); return; } else { // moramo ovako, da bi dsNarucivanje kao globalna promenljiva dobila vrednost zbog Exporta dsNarucivanje = objNarucivanjeDB.DajNarudzbePremaRobi(txbFilterNazivRobe.Text); NapuniGrid(dsNarucivanje); } } 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;
-
__________________________________________________________ 22
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!"); // moramo ovako da bi globalna promenljiva dsNarucivanje dobila vrednost zbog eksporta dsNarucivanje = objNarucivanjeDB.DajSveNarudzbe(); NapuniGrid(dsNarucivanje); 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!"); } } }
10.2. Listing biblioteke Klase podataka
clsNarucivanje
using System; using System.Collections.Generic; using System.Linq; using System.Text; 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
-
__________________________________________________________ 23
_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; } } } }
clsNarucivanjeLista
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace KlasePodataka { public class clsNarucivanjeLista { // NAMENA: Tipizirana lista objekata klase clsNarucivanje, sa svim CRUD operacijama nad listom // atributi private List pListaNarucivanja; // property public List ListaNarucivanja { get {
-
__________________________________________________________ 24
return pListaNarucivanja; } set { if (this.pListaNarucivanja != value) this.pListaNarucivanja = value; } } // konstruktor public clsNarucivanjeLista() { pListaNarucivanja = new List(); } // 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); } } }
clsNarucivanjeDB using System; using System.Collections.Generic; using System.Linq; using System.Text; // using SqlDBUtils; using System.Data; namespace KlasePodataka { public class clsNarucivanjeDB { // atributi private clsSqlKonekcija objSqlKonekcija; private clsSqlTabela objSqlTabela; private DataSet dsNarucivanje; // konstruktor public clsNarucivanjeDB(string MSSQLInstanca, string NazivBazePodataka) { objSqlKonekcija = new clsSqlKonekcija(MSSQLInstanca, "", NazivBazePodataka);
-
__________________________________________________________ 25
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; } } } }
10.3. Listing biblioteke SQLDBUtils using System; using System.Collections.Generic; using System.Linq; using System.Text; //
-
__________________________________________________________ 26
using System.Data.SqlClient; namespace SqlDBUtils { public class clsSqlKonekcija { /* ODGOVORNOST: Konekcija na celinu baze podataka, SQL server tipa */ #region Atributi private SqlConnection pKonekcija; // private string pPutanjaSQLBaze; private string pNazivBaze; private string pNazivSQL_DBMSinstance; private string pStringKonekcije; #endregion #region Konstruktor public clsSqlKonekcija(string nazivSQL_DBMSInstance, string putanjaSqlBaze, string NazivBaze) { // preuzimanje vrednosti u privatne atribute pPutanjaSQLBaze = putanjaSqlBaze; pNazivBaze = NazivBaze; pNazivSQL_DBMSinstance = nazivSQL_DBMSInstance; // pripremanje stringa konekcije, dodato 22.3.2020. pStringKonekcije = ""; pStringKonekcije = FormirajStringKonekcije(); } // preklapajuci konstruktor, kada dobijemo spolja string konekcije public clsSqlKonekcija(string noviStringKonekcije) { pStringKonekcije = noviStringKonekcije; // u ovom slucaju se ne poziva metoda FormirajStringKonekcije } // preklapajuci konstruktor, bez stringa konekcije public clsSqlKonekcija() { } #endregion #region Privatne metode private string FormirajStringKonekcije() // promenjen naziv { string mStringKonekcije=""; if (pPutanjaSQLBaze.Length.Equals(0) || pPutanjaSQLBaze == null) { mStringKonekcije = "Data Source=" + pNazivSQL_DBMSinstance + " ;Initial Catalog=" + pNazivBaze + ";Integrated Security=True"; } else { mStringKonekcije = "Data Source=.\\" + pNazivSQL_DBMSinstance + ";AttachDbFilename=" + pPutanjaSQLBaze + "\\" + pNazivBaze + ";Integrated Security=True;Connect Timeout=30;User Instance=True"; } return mStringKonekcije; } #endregion #region Javne metode public string StringKonekcije { get { return pStringKonekcije; } set { pStringKonekcije = value; } }
-
__________________________________________________________ 27
public bool OtvoriKonekciju() { bool uspeh; pKonekcija = new SqlConnection(); pKonekcija.ConnectionString = pStringKonekcije; // 22.3.2020. s obzirom da se na konstruktoru formira i smesta string konekcije u pStringKonekcije, onda se ovde samo otvara // ovo je bolje resenje nego da se ovde pozove i kreiranje stringa konekcije, s obzirom na SOLID princip Single Responsibility i a sto jezgrovitije radimo posao koji je dat (da se ne radi ono sto nije u nazivu) try { pKonekcija.Open(); uspeh = true; } catch { uspeh = false; } return uspeh; } public SqlConnection DajKonekciju() { return pKonekcija; } public string DajStringKonekcije() // dodato 22.3.2020. { return pStringKonekcije; } public void ZatvoriKonekciju() { pPutanjaSQLBaze = ""; pKonekcija.Close(); pKonekcija.Dispose(); } #endregion } }
clsTabela
using System; using System.Collections.Generic; using System.Linq; using System.Text; // using System.Data.SqlClient; namespace SqlDBUtils { public class clsSqlTabela { #region Atributi private string pNazivTabele; private clsSqlKonekcija pKonekcija; private SqlDataAdapter pAdapter; private System.Data.DataSet pDataSet; #endregion #region Konstruktor public clsSqlTabela(clsSqlKonekcija Konekcija, string NazivTabele)
-
__________________________________________________________ 28
{ pKonekcija = Konekcija; pNazivTabele = NazivTabele; } #endregion #region Privatne metode private void KreirajAdapter(string SelectUpit, string InsertUpit, string DeleteUpit, string UpdateUpit) { SqlCommand mSelectKomanda, mInsertKomanda, mDeleteKomanda, mUpdateKomanda; mSelectKomanda = new SqlCommand(); mSelectKomanda.CommandText = SelectUpit; mSelectKomanda.Connection = pKonekcija.DajKonekciju(); mInsertKomanda = new SqlCommand(); mInsertKomanda.CommandText = InsertUpit; mInsertKomanda.Connection = pKonekcija.DajKonekciju(); mDeleteKomanda = new SqlCommand(); mDeleteKomanda.CommandText = DeleteUpit; mDeleteKomanda.Connection = pKonekcija.DajKonekciju(); mUpdateKomanda = new SqlCommand(); mUpdateKomanda.CommandText = UpdateUpit; mUpdateKomanda.Connection = pKonekcija.DajKonekciju(); pAdapter = new SqlDataAdapter(); pAdapter.SelectCommand = mSelectKomanda; pAdapter.InsertCommand = mInsertKomanda; pAdapter.UpdateCommand = mUpdateKomanda; pAdapter.DeleteCommand = mDeleteKomanda; } private void KreirajDataset() { pDataSet = new System.Data.DataSet(); pAdapter.Fill(pDataSet, pNazivTabele); } private System.Data.DataTable KreirajDataTable(System.Data.DataSet noviDataSet) { return noviDataSet.Tables[0]; } private void ZatvoriAdapterDataset() { pAdapter.Dispose(); pDataSet.Dispose(); } #endregion #region Javne metode public System.Data.DataSet DajPodatke(string SelectUpit) // izdvaja podatke u odnosu na dat selectupit { KreirajAdapter(SelectUpit, "", "", ""); KreirajDataset(); return pDataSet; } public int DajBrojSlogova() { int BrojSlogova = pDataSet.Tables[0].Rows.Count; return BrojSlogova;
-
__________________________________________________________ 29
} public bool IzvrsiAzuriranje(string Upit) // izvrzava azuriranje unos/brisanje/izmena u odnosu na dati i upit { // bool uspeh = false; SqlConnection mKonekcija; SqlCommand Komanda; SqlTransaction mTransakcija = null; try { mKonekcija = pKonekcija.DajKonekciju(); // aktivan kod // povezivanje Komanda = new SqlCommand(); Komanda.Connection = mKonekcija; Komanda = mKonekcija.CreateCommand(); // pokretanje // NE TREBA OPEN JER DOBIJAMO OTVORENU KONEKCIJU KROZ KONSTRUKTOR // mKonekcija.Open(); mTransakcija = mKonekcija.BeginTransaction(); Komanda.Transaction = mTransakcija; Komanda.CommandText = Upit; Komanda.ExecuteNonQuery(); mTransakcija.Commit(); uspeh = true; } catch { mTransakcija.Rollback(); uspeh = false; } return uspeh; } // preklapajuca metoda kada dobijemo vise upita da se izvrsi u transakciji public bool IzvrsiAzuriranje(List ListaUpita) // izvrzava azuriranje unos/brisanje/izmena // moze se dodeliti kao parametar lista od vise upita // sada transakcija ima smisla, jer izvrsava vise upita u paketu { // bool uspeh = false; SqlConnection mKonekcija; SqlCommand Komanda; SqlTransaction mTransakcija = null; try { mKonekcija = pKonekcija.DajKonekciju(); // aktivan kod // povezivanje Komanda = new SqlCommand(); Komanda.Connection = mKonekcija; Komanda = mKonekcija.CreateCommand(); // pokretanje // NE TREBA OPEN JER DOBIJAMO OTVORENU KONEKCIJU KROZ KONSTRUKTOR // mKonekcija.Open(); string Upit=""; mTransakcija = mKonekcija.BeginTransaction(); Komanda.Transaction = mTransakcija; for (int i = 0; i < ListaUpita.Count(); i++) { Upit = ListaUpita[i]; Komanda.CommandText = Upit; Komanda.ExecuteNonQuery(); }
-
__________________________________________________________ 30
mTransakcija.Commit(); uspeh = true; } catch { mTransakcija.Rollback(); uspeh = false; } return uspeh; } #endregion
} }