Sovelluksen jako palvelimiksi: Palvelin on sille annettuun vastuulliseen tehtävään erikoistunut sovellusosa. Käyttöliittymäpalvelin (Web-palvelin) vastaa käyttöliittymän toteuttamisesta. Web-palvelin toteuttaa käyttäjän tarvitsemat HTML-sivut ja ASP-sivut. Liiketoimintapalvelin on vastuussa käyttäjän tarvitsemien palvelujen toteuttamisesta. Käyttäjän käyttöliittymä on yhteydessä ainoastaan liiketoimintapalvelimeen. Tietovarastopalvelin on vastuussa tiedon välityksestä liiketoimintapalvelimen ja tietovaraston kesken. Tietovarastopalvelin tarjoaa sekä tiedon tallentamispalveluja että tiedon hakupalveluja liiketoimintapalvelimelle.
Mistä palvelimet löytyvät: Liiketoimintapalvelin Tiedonhallintapalvelin Käyttöliittymä (Web-palvelin)
Sovelluksen jako palvelimiksi: Käyttöliittymäpalvelin (Web-palvelin) toimittaa käyttäjälle kahden tyyppisiä XHTML-sivuja: Staattiset sivut ovat vakiomuotoisia XHTML-sivuja, jotka toteutetaan Web-palvelimessa htm-tarkentimella varustettuina sivuina. Dynaamiset sivut ovat sisällöltään muuttuvia sivuja, jotka toteutetaan Web-palvelimessa ASP.NET-sivuina. ASP.NET-sivujen sisältöön vaikuttaa tyypillisesti mm. tietokannasta saatava tieto.
Sovelluksen jako palvelimiksi: ASP.NET- sivut esiintyvät webpalvelimessa tarkentimella aspxvarustettuina sivuina. aspx-tarkentimella varustettu sivu muodostuu tavallisesta XHTML-koodista sekä koodiin upotetusta ASP.NET -koodista. ASP.NET-sivun koodi sisältää ensisijassa kontrollien esittämiseen ja käyttöön tarvittavaa tietoa. Kuhunkin aspx-tarkentimella varustettuun sivuun liittyy valitun ohjelmointikielen mukainen koodisivu (code-behind). jossa on mm. varsinaisen aspx-sivun kontrollien tapahtumankäsittelijät.
Kuinka ASP.NET sivu toimii? Käyttäjän pyytäessä Web-palvelimelta aspx-tyyppistä ASP.NET sivua Web-palvelin käynnistää ns. ISAPI-filtterin. Ensimmäisellä kutsukerralla ISAPI-filtteri lähettää käyttäjän selaimelle XHTML-sivun koodin sekä tähän koodiin upotetut kontrollit. Kontrollit on varustettu tapahtumantunnistimilla. Kun käyttäjä sivun saatuaan täyttää sivun ja painaa komentopainiketta, aktivoi ISAPI-filtteri komentopainikkeeseen liittyvän tapahtumankäsittelijän aspx-sivuun liittyvällä koodisivulla.
Kuinka ASP.NET sivu toimii? Tapahtumankäsittelijän tehtävänä on suorittaa kaikki komentopainikkeen painamiseen liittyvät tehtävät. Tehtävien suorittaminen tapahtuu sekä ASP.NET aspx-sivuun liittyvälle koodisivulle toteutettujen funktioiden että liiketoimintakerroksessa olevien palveluiden avulla.
Sovellettava rakennemalli: Tieto siirretään käyttöliittymästä liiketoimintaluokkiin Tieto siirretään liiketoimintaluokista tietokantaan (transaktioita käyttäen) Web-palvelin (Käyttöliittymä) Liiketoimintapalvelin Tiedonhallintapalvelin Tieto siirretään liiketoimintaluokista käyttöliittymään Tieto siirretään tietokannasta liiketoimintaluokkiin
Sovellettava rakennemalli: Web-palvelimen (käyttöliittymän) vastuut: toteuttaa käyttöliittymään liittyvät staattiset xhtml-sivut toteuttaa käyttöliittymään liittyvä tyyli tyylisivujen avulla toteuttaa käyttöliittymään liittyvät ASP.NET sivut Web-palvelimen ASP.NET-sivujen tapahtumankäsittelijöiden vastuut: säilyttää käyttöliittymän toiminnallisuus käyttötilanteen mukaisena (mm. aktivoimalla ja passivoimalla komentopainikkeita) pyytää liiketoimintakerrokselta tarvittavat palvelut siirtää liiketoimintakerrokselle käyttäjän käyttöliittymään syöttämät tiedot toimenpiteitä varten
Sovellettava rakennemalli: Liiketoimintapalvelimen vastuut: luoda palvelujen edellyttämät kohdeluokkien oliot. Rakennemallissamme vain liiketoimintapalvelimella on oikeus luoda kohdeluokkien olioita luoda palvelimeen kohdeluokkien vaatima oliohierarkia ja oliohierarkian vaatimat tekniset luokat vastata niistä eheyssäännöistä, jotka on asetettu liiketoimintapalvelimen vastuulle toteuttaa käyttöliittymään tarvitsemat palvelut pyytää tiedonhallintapalvelimelta niitä palveluita, joita käyttöliittymän tarvitsemien palvelujen toteuttaminen edellyttää
Sovellettava rakennemalli: Tiedonhallintapalvelimen vastuut: luoda palvelujen edellyttämä SQL-koodi. Rakennemallissamme vain tiedonhallintapalvelimella on oikeus luoda SQL-koodia luoda yhteys tiedonhallintajärjestelmään palvelujen toteuttamista varten toteuttaa liiketoimintapalvelimen pyytämiä palveluita. Rakennemallissamme tiedonhallintapalvelimen palveluita saa käyttää vain liiketoimintapalvelin. vastata niistä eheyssäännöistä, jotka on asetettu tiedonhallintapalvelimen vastuulle vastata tapahtumankäsittelyn vaatimasta eheyden valvonnasta ja tietokannan tietojen versioinnista
Esimerkin alkutilanne (löytyy zip-tiedostosta FillariVaihe1.zip): Sovelluksen aloitusikkuna (staattinen xhtml-sivu):
Esimerkin alkutilanne: Sovelluksen asiakastietoikkuna (ASP.NET-sivu):
Esimerkin alkutilanne: Sovelluksen kohdeluokat: Osoite Osoite + <property> lahiosoite + <property> postitoimipaikka + <property> postinumero tai Asiakas Asiakas + <property> asiaksnumero + <property> nimi + <property> alennusprosentti + <property> versio
Tiedon siirtäminen käyttöliittymästä liiketoimintaluokkiin. Aluksi aspx-sivuun liittyvään koodisivuun toteutetaan metodi, joka siirtää tiedot käyttöliittymäkontrolleista liiketoimintakerroksen kohdeluokkiin. Metodi voi olla esimerkiksi seuraavan tapainen: private bool RuudultaOlioon(Asiakas asi) { try { asi.asiakasnumero = Int32.Parse(TexAsiakasNumero.Text); asi.nimi = TexAsiakasNimi.Text; asi.lahiosoite = TexLahiosoite.Text; asi.postitoimipaikka = TexPostitoimipaikka.Text; asi.postinumero = TexPostinumero.Text; asi.alennusprosentti = Int32.Parse(TexAlennusProsentti.Text); asi.versio = Int32.Parse(LabVersio.Text); catch { LabVirhe.Text = "Joko asiakasnumero tai alennusprosentti ei ole numeerinen."; return false; LabVirhe.Text = ""; return true; Parametrina viitemuuttuja Asiakas-olioon Muutetaan merkkijono kokonaisluvuksi konversion avulla try-catch lohko tarvitaan mahdollisia konversiovirheitä varten Palautetaan tarvittaessa selväkielinen virheilmoitus
Tiedon siirtäminen liiketoimintaluokista käyttöliittymään. Vastaavasti aspx-sivuun liittyvään koodisivuun toteutetaan metodi, joka siirtää tiedot liiketoimintakerroksen kohdeluokasta käyttöliittymäkontrolleihin. Metodi voi olla esimerkiksi seuraavan tapainen: private bool OliostaRuudulle(Asiakas asi) { try { TexAsiakasNumero.Text = asi.asiakasnumero.tostring(); TexAsiakasNimi.Text = asi.nimi; TexLahiosoite.Text = asi.lahiosoite; TexPostitoimipaikka.Text = asi.postitoimipaikka; TexPostinumero.Text = asi.postinumero; TexAlennusProsentti.Text = asi.alennusprosentti.tostring(); LabVersio.Text = asi.versio.tostring(); catch { LabVirhe.Text = "Asiakkaan tietojen esittäminen ei onnistu."; return false; LabVirhe.Text = ""; return true; Parametrina viitemuuttuja Asiakas-olioon Muutetaan kokonaisluku merkkijonoksi konversion avulla try-catch lohko tarvitaan mahdollisia konversiovirheitä varten Palautetaan tarvittaessa selväkielinen virheilmoitus
Tiedon siirtäminen käyttöliittymästä liiketoimintaluokkiin. Seuraavaksi liiketoimintapalvelimelle toteutetaan AsiakasKontrolkontrollikuokka käyttöliittymän asiakkaaseen liittyvien palveluiden toteuttamista varten. AsiakasKontrol-luokassa on ominaisuutena viitemuuttuja Asiakas-olioon. Asiakas-oliohan oli kohdeluokan ilmentymä, joten sen saa luoda vain liiketoimintapalvelimeen kuuluva luokka. AsiakasKontrol + <property> asi :Asiakas Asiakas + <property> asiaksnumero + <property> nimi + <property> alennusprosentti + <property> versio
Tiedon siirtäminen käyttöliittymästä liiketoimintaluokkiin. Tiedon siirtäminen käyttöliittymäkontrolleista liiketoimintakerroksen kohdeluokkiin edellyttää, että käytettävissä on viitemuuttuja tarvittavaan kohdeluokkaan. Liiketoimintakerroksen kontrolliluokan tehtävänä on luoda tarvittavat kohdeluokat ja luovuttaa niiden viitemuuttujat käyttäjille. Kontrolliluokan toteutus saattaa näyttää alkuosaltaan tältä: public class AsiakasKontrol { private Asiakas asi; public AsiakasKontrol() { asi = new Asiakas(); public Asiakas LuovutaAsiakas () { return asi ;.
Tiedonhallintapalvelin: Liiketoimintapalvelin tarvitsee omien palveluidensa toteuttamista varten tiedonhallintapalvelimen. Tiedonhallintapalvelinta edustaa sovelluksessa luokka Tietokanta. Toistaiseksi luokassa ei ole ominaisuuksia eikä metodeita. Tietokanta-luokan lisäämisen jälkeen Solution Explorer kehys näyttää tältä:
Seuraavaksi selvitetään mitä sovelluksessa tapahtuu kun käyttäjä yllä olevassa tilanteessa haluaa tallentaa uuden asiakkaan tiedot ja painaa Tallenna komentopainiketta.
Asiakkaan lisääminen (katso edellinen kalvo): 1. Asiakas painaa komentopainiketta Tallenna 2. Asiakkaan selaimesta siirtyvät näytön tiedot Web-palvelimelle HTTP-protokollan avulla. 3. Web-palvelimessa aktivoituu lomakkeen Tallenna-komentopainikkeeseen liittyvän Clicktapahtuman tapahtumankäsittelijä ButTallenna_Click 4. Tapahtumankäsittelijä luo liiketoimintapalvelimen AsiakasKontrol-olion 5. AsiakasKontrol-olion oletusmuodostin luo Asiakas-olion 6. Tallenna-komentopainikkeen tapahtumankäsittelijä pyytää AsiakasKontrol-oliolta viitemuuttujan luotuun Asiakas-olioon 7. Tallenna-komentopainikkeen tapahtumankäsittelijä siirtää käyttöliittymän tiedot Asiakasolioon 8. Tallenna-komentopainikkeen tapahtumankäsittelijä pyytää AsiakasKontrol-oliota tallentamaan uuden asiakkaan tiedot 9. AsiakasKontrol-olio luo uuden Tietokanta-olion 10. AsiakasKontrol-olio pyytää Tietokanta-oliota tallentamaan asiakkaan tiedot ja antaa Tietokanta-oliolle parametrina viitemuuttujan Asiakas-olioon 11. Tietokanta-olio palauttaa tiedon asiakkaan lisäämisen onnistumisesta AsiakasKontrololiolle 12. AsiakasKontrol-olio palauttaa tiedon asiakkaan lisäämisen onnistumisesta Tallennakomentopainikkeen tapahtumankäsittelijälle 13. Tallenna-komentopainikkeen tapahtumankäsittelijä palauttaa tiedon uuden asiakkaan lisäämisen onnistumisesta käyttäjälle
Tapahtumankäsittelijän toteuttaminen Tallenna-komentopainikkeelle: protected void ButTallenna_Click(object sender, EventArgs e) { bool b; string s = ""; AsiakasKontrol ask = new AsiakasKontrol(); b = this.ruudultaolioon (ask.luovutaasiakas()); if (ButPoista.Enabled == false) { b = ask.lisaa(ref s); if (b == true) { ButPoista.Enabled = true; LabVirhe.Text = "Asiakkaan lisääminen onnistui."; return; else { LabVirhe.Text = s; return; Tapahtumankäsittelijä Luodaan AsiakasKontrol-olio Viedään tiedot Asiakas-olioon Tutkitaan, oliko tehtävänä uuden asiakkaan lisääminen tai vanhan muuttaminen. Kutsutaan Lisaa-metodia suorittamaan asiakkaan tietojen lisääminen Onnistuiko? Vanhan tiedon muuttamista ei ole toistaiseksi toteutettu
Lisää-metodin toteuttaminen AsiakasKontrol-luokkaan: public bool Lisaa(ref string message) { bool b; Tietokanta tk = new Tietokanta(); b = tk.asiakaslisaa(asi); if (b == false) { message = "Asiakkaan tietojen lisääminen ei onnistunut."; else { message = ""; return b; Lisaa-metodi palauttaa sekä totuusarvon että tarvittaessa virheilmoituksen (ref string message) Luodaan Tietokanta-olio Kutsutaan tietokantaolion AsiakasLisaa-metodia Onnistuiko lisäys?
Tietokanta luokan toteuttaminen (jatkuu seuraavassa kalvossa):.. using System.Data.SqlClient; /// <summary> /// Tietokanta-luokka on vastuussa: /// - yhteydenpidosta tietokantaan /// - transaktioista /// - commit- ja rollback -operaatioista /// - SQL-lauseiden muodostamisesta /// - SQL -lauseiden suorittamisesta /// - operaatioiden turvallisuudesta. /// </summary> public class Tietokanta { private SqlTransaction dbtrans; private SqlConnection dbconn; // Connection string tietokantaan static private string cnstr = "; public Tietokanta() {. Tarvitaan kirjastoa System.Data.SqlClient Tietokanta on monesta vastuussa SqlTransaction -luokka on tarpeen transaktioiden käyttämisessä SqlConnection luokka vastaa yhteyden muodostamisesta tiedonhallintajärjestelmään Connection string löytyy automaattisesti seuraavan kalvon ohjeiden avulla. Muista, että kenoviiva \ vaatii kaksi kenoviivaa \\ C#-merkkijonovakiossa Oletusmuodostin on tyhjä
Tietokannan connection string muuttujan arvon automaattinen haku: 1. Osoita Server Explorer kehyksessä ylinnä olevaa Data Connection ikonia hiirellä ja paina hiiren oikeaa näppäintä 2. Valitse valikosta toiminto Add Connection. 3. Esiin tulee Add Connection dialogi. Anna Data Source kentän arvoksi Microsoft SQL Server (SqlClient). 4. Aseta Server Name kentän arvoksi do3023l18\sqlexpress, missä do3023l18 on koneesi nimi tai tunnus 5. Valitse kirjautumistavaksi Use Windows Authentication 6. Valitse yhteydenmuodostamistavaksi Select or enter a database name ja valitse alasvetovalikosta käsittelemäsi tietokanta 7. Paina Test Connection komentopainiketta. 8. Mikäli saat palautteeksi tiedon onnistuneesta yhteydenmuodostamisesta paina lopuksi sivun alareunassa olevaa OK-komentopainiketta. Muussa tapauksessa korjaa virheellinen määrittely 9. Osoita hiirellä juuri muodostamaasi yhteyttä Server Explorer kehyksessä. Properties-kehykseen ilmestyy yhteyden ominaisuudet. Niiden joukosta löytyy myös yhteyden Connection String. 10. Kopioi Connection String arvo tietokantaluokkasi staattiseen muuttujaan ja muista korvata merkkijonossa esiintymä kenoviiva kahdella kenoviivalla.
Toteutuksen viestiyhteyskaavio: : käyttäjä : asiakas : AsiakasKontrol : Asiakas : Tietokanta Tallenna New LuovutaAsiakas New RuudultaOlioon Asiakasnumero Nimi Lisaa New AsiakasLisaa Asiakasnumero Nimi
public bool AsiakasLisaa(Asiakas asi) { bool b; try { dbconn = new SqlConnection(cnstr); Määritellään SqlConncetion objekti ja avataan yhteys tietokantaan. dbconn.open(); dbtrans = dbconn.begintransaction();. Aloitetaan transaktio. Itse SQL-lauseen suoritus tapahtuu tässä (koodi on seuraavalla kalvolla) catch (SqlException ex){ b = false; if (dbtrans!= null) { dbtrans.rollback(); finally { if (dbconn.state == ConnectionState.Open) { dbconn.close(); return b; Virhetilanteissa paluuarvo on false ja transaktiolle tehdään tarvittaessa Rollback. Lopuksi suljetaan yhteys tietokantaan mikäli se on vielä auki. HUOMAA: Tämä perusrunko sopii transaktionhallinnan kannalta muidenkin toimintojen kuin tietokantaan lisäämisen perusrungoksi.
Tietokantaan lisäämisen toteutus (jatkoa edelliseltä sivulta) SqlCommand sqlcmd = new SqlCommand(); sqlcmd.commandtext = "INSERT INTO asiakas (anumero, animi, alahiosoite, apostitoimipaikka, " + "apostinumero, aalennusprosentti, aversio) VALUES (" + asi.asiakasnumero.tostring() + ", '" + asi.nimi + "', '" + asi.lahiosoite + "', '" + asi.postitoimipaikka + "', '" + asi.postinumero + "', " + asi.alennusprosentti.tostring() + ", " + asi.versio.tostring() + ") "; sqlcmd.connection = dbconn; sqlcmd.transaction = dbtrans; sqlcmd.executenonquery(); dbtrans.commit(); b = true; Luodaan SqlCommand-objekti ja asetetaan sen sisällöksi käytetty SQL-lause Kiinnitetään SqlCommand-objektiin SqlConnection-objekti ja SqlTransaction-objekti Suoritetaan SQL-lause Onnistuneen suorituksen jälkeen tehdään transaktiolle Commit eli hyväksytään transaktio. Palautetaan tieto onnistumisesta.
Sovellus toteutettuna siten, että tietokantaan lisääminen onnistuu, löytyy zip-tiedostosta FillariVaihe2.zip Koko sovellus toteutettuna siten, että tietokannan ylläpitäminen onnistuu, löytyy zip-tiedostosta FillariVaihe4.zip