Univerzitet u Novom Sadu Tehnički fakultet »MihajloPupin ... · dat spisak fajlova koji čine...

31
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

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

    } }