Powered by TCPDF (www.tcpdf.org)
Academiejaar 2012–2013
Geassocieerde faculteit Toegepaste Ingenieurswetenschappen Valentin Vaerwyckweg 1 – 9000 Gent
Ontwikkeling van een Remote Controlled Alert & Task Agent
Masterproef voorgedragen tot het behalen van het diploma van Master in de industriële wetenschappen: informatica
Glenn JACOB Promotoren: ing. Wim VAN DEN BREEN Joris VAN MALDEGHEM (ICORDA) Begeleider:
Sander WOLLAERT (ICORDA)
De auteur en promotor geven de toelating deze scriptie voor consultatie beschikbaar te stellen en delen ervan te kopi¨eren voor persoonlijk gebruik. Elk ander gebruik valt onder de beperkingen van het auteursrecht, in het bijzonder met betrekking tot de verplichting uitdrukkelijk de bron te vermelden bij het aanhalen van resultaten uit deze scriptie. The author and promoter give the permission to use this thesis for consultation and to copy parts of it for personal use. Every other use is subject to the copyright laws, more specifically the source must be extensively specified when using from this thesis. Gent, Juni 2013 De promotor
Wim Van den Breen
De begeleider
Sander Wolleart
De auteur
Glenn Jacob
Woord vooraf Vooreerst wil ik dhr. Sander Wollaert bedanken in dit woord vooraf. Hij heeft mij altijd goed geholpen en mij op de juiste momenten in de goede richting gestuurd. Door hem heb ik een degelijk programma kunnen opleveren. Ik wil ook iedereen bedanken die een positieve bijdrage heeft geleverd aan deze masterproef. Daarnaast wil ik de mensen van het Software Application Services team van ICORDA bedanken. Zij waren namelijk aangename collega’s die voor een toffe werksfeer hebben gezorgd. Ik wil ook Wim Van den Breen bedanken voor de goede begeleiding. Hij heeft mij handige raad gegeven om de deze scriptie op te stellen. Naast de hulp met de scriptie kon ik ook altijd rekenen op zijn volledige interesse in het werk dat ik heb geleverd bij ICORDA. Glenn Jacob Aalst 12 Juni 2013
iv
Inleiding Deze masterproef zal handelen over de ontwikkeling van een Remote Controlled Alert & Task Agent (RCATA). De agent moet in staat zijn om gegevens periodiek te analyseren en op basis hiervan alerts te genereren. Deze gegevens handelen over hardware of software. Een alert moet worden gegenereerd als er een bepaald gegeven als alarmerend wordt beschouwd door de agent. Bij deze alert hoort ook een taak. Deze taak zal worden uitgevoerd wanneer de alert wordt gegenereerd. Een taak kan het probleem oplossen, maar zal in de eerste plaats de verantwoordelijke op de hoogte brengen van het probleem. Er zal dus een systeem worden opgezet dat zal zorgen voor de analyse van bepaalde gegevens, maar op wat is de analyse gebaseerd? Er zal ook een applicatie nodig zijn die een configuratie voor de analyse kan instellen. In de configuratie wordt dan aangegeven wanneer er precies een alert zal worden gegenereerd. Het is dan de bedoeling dat de analyse van deze configuratie gebruikmaakt om al dan niet alerts aan te maken. In de configuratie zullen ook de taken die bij de alerts horen worden gedefini¨eerd. Naast de applicatie voor de configuratie zal er ook een applicatie worden aangemaakt die alle alerts op een overzichtelijke manier aan de gebruiker toont. De RCATA zal een grote taak die vroeger helemaal manueel moest worden uitgevoerd, automatiseren. Omdat ik ook een grote interesse heb in automatisering van bepaalde taken heb ik voor deze masterproef gekozen. De omgeving waarin de RCATA moet worden ontwikkeld is C# met het .NET framework waarmee ik bij het begin van deze masterproef niet echt mee vertrouwd was. Zoals bij ieder groter project wordt er klein begonnen en dan wordt de bestaande applicatie verder uitgebreid tot het doel is bereikt. Ook hier was dit zo, de masterproef is begonnen met een simpele applicatie die gegevens kon ophalen en analyseren zonder dat er werd rekening gehouden met een configuratie. Naarmate de masterproef vorderde werd er een systeem ontwikkeld dat voldoet aan de eisen van de doelstelling. Met deze programeeromgeving en deze manier van werken waren er veel kansen om verschillende dingen bij te leren. Deze scriptie zal beginnen met een overzicht van het probleem en de doelstelling van deze masterproef. Vervolgens zullen een aantal begrippen worden verduidelijkt. In de v
vi hoofdstukken die daarop volgen zullen het model van het programma en de technologie¨en die daarin gebruikt werden uitgebreid worden besproken. In de twee laatste hoofdstukken zal de structuur van de verschillende applicaties naar voor komen en hoe de besproken technologie¨en hierin zijn gebruikt. Veel van de informatie die hierin voorkomt is afkomstig van het internet. De reden hiervoor is dat de meeste technologie¨en die gebruikt werden in deze masterproef zijn ontwikkeld door Microsoft en DevExpress. Deze bedrijven voorzien al hun documentatie online.
Abstract Nederlands: Deze masterproef gaat over het ontwikkelen van een systeem dat kan detecteren of gegevens alarmerend zijn. Hierbij maakt het gebruik van een pollingmechanisme om de gegevens op te halen, te analyseren en eventueel alerts te genereren. Een configuratie zal bepalen welke gegevens als alarmerend worden beschouwd. Deze configuratie kan aangepast worden, en treedt meteen in werking wanneer de aanpassing is bewaard. Hierbij wordt er gebruikgemaakt van een gebruikersapplicatie om de configuratie op te stellen. Om de gebruiksvriendelijkheid te verhogen zal elke gebruiker de algemene configuratie kunnen aanpassen naar zijn eigen wensen. Hierbij wordt de algemene configuratie niet aangepast, maar er wordt achterliggend een gebruikersspecifieke configuratie aangemaakt. Op deze manier kan een gebruiker strengere of minder strenge voorwaarden opleggen voor alerts aan te maken. Zijn de voorwaarden voldaan, dan wordt die gebruiker daarvan op de hoogte gebracht. Bij het detecteren van een alarmerend gegeven wordt ook een taak uitgevoerd. Deze taak brengt de verantwoordelijke(n) op de hoogte, maar er kunnen nog extra taken toegevoegd worden. Een laatste applicatie zal gebruikt worden om alle alerts op een overzichtelijke manier te bekijken.
vii
Abstract English: The assignment of this thesis is the development of an independent system to detect alarming values in data. This data is analysed by an application that uses a polling mechanism. The polling mechanism will generate alerts when a record in the data is alarming. A configuration is used to determine which values are considered alarming. This configuration is configured in a separate application. When the user has finished editing the configuration, it is saved, the configuration is immediately used by the polling mechanism. Next to the main configuration there is a configuration for every user. The user can creates an independent configuration for him/her only, without changing the main configuration. The user configuration is edited in a separate application. Because every user can have different conditions for finding alarming values, the polling mechanism has to check all the conditions for every user and the general condition to know which people to inform. When an alarming value is found, a task is executed as well. The minimum task is to inform the responsible person(s), but other tasks can be specified. Another application will be created to view the generated alerts.
viii
Inhoudsopgave 1 Huidige Situatie en Probleemstelling 1.1 Algemeen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Opstelling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 Probleemstelling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1 1 1 2
2 Doelstelling
3
3 Algemene Begrippen 3.1 Alerts en Taken . . . . . . 3.2 Alert Filter en Alert Filter 3.3 Monitoring Facts . . . . . 3.4 De Alert & Task Agent . .
. . . .
5 5 5 6 6
. . . . . . . . . .
8 8 8 9 9 10 11 13 13 14 17
. . . . . . .
20 20 20 20 22 22 23 25
. . . . . Extensie . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
4 Het Model 4.1 Het Model in detail . . . . . . . . . . . . . 4.1.1 De Analysegegevens . . . . . . . . 4.1.2 De Configuratie . . . . . . . . . . . 4.1.2.1 General Alert Filters . . . 4.1.2.2 User Alert Filters . . . . . 4.1.2.3 Alert Filter Extensies . . 4.1.2.4 Task klassen . . . . . . . 4.1.2.5 Overzicht . . . . . . . . . 4.1.3 De Alerts . . . . . . . . . . . . . . 4.2 Algoritme voor de Analyse van Monitoring 5 Gebruikte technologie¨ en 5.1 ADO Entity Framework . . . . . . . . 5.1.1 Entity Datamodel . . . . . . . . 5.1.2 Communicatie met de databank 5.1.3 Gebruik . . . . . . . . . . . . . 5.1.3.1 Databank eerst . . . . 5.1.3.2 Code eerst . . . . . . . 5.1.3.3 Implementatie . . . .
ix
. . . . . . .
. . . . . . .
. . . .
. . . .
. . . .
. . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Facts .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . .
. . . . . . . . . .
. . . . . . .
. . . .
. . . . . . . . . .
. . . . . . .
. . . .
. . . . . . . . . .
. . . . . . .
. . . .
. . . . . . . . . .
. . . . . . .
. . . .
. . . . . . . . . .
. . . . . . .
. . . .
. . . . . . . . . .
. . . . . . .
. . . .
. . . . . . . . . .
. . . . . . .
. . . .
. . . . . . . . . .
. . . . . . .
. . . .
. . . . . . . . . .
. . . . . . .
. . . .
. . . . . . . . . .
. . . . . . .
. . . .
. . . . . . . . . .
. . . . . . .
. . . .
. . . . . . . . . .
. . . . . . .
. . . .
. . . . . . . . . .
. . . . . . .
Inhoudsopgave 5.2 5.3 5.4 5.5
5.6
5.7
Het OData protocol . . . . . . . . . . . . . . 5.2.1 Gebruik en Werking . . . . . . . . . Language Integrated Query (LINQ) . . . . . DevExpress . . . . . . . . . . . . . . . . . . Model View Viewmodel (MVVM) . . . . . . 5.5.1 Model View Controller (MVC) . . . . 5.5.2 Algemeen . . . . . . . . . . . . . . . 5.5.3 MVVM met DevExpress . . . . . . . Windows Services . . . . . . . . . . . . . . . 5.6.1 Een Windows service maken . . . . . 5.6.2 Installeren van een Windows service . Team Foundation Server . . . . . . . . . . .
x . . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
6 Componenten van de Remote Controlled Alert & Task 6.1 De verschillende componenten . . . . . . . . . . . . . . . 6.2 De Data Service . . . . . . . . . . . . . . . . . . . . . . . 6.3 De Windows Service . . . . . . . . . . . . . . . . . . . . 6.4 De Gebruikersapplicatie . . . . . . . . . . . . . . . . . . 6.4.1 Alert Viewer . . . . . . . . . . . . . . . . . . . . . 6.4.2 De Configuratie-editor . . . . . . . . . . . . . . . 6.4.2.1 Configuratie van een alert filter . . . . . 6.4.2.2 Functies van de configuratie-editor . . . 6.4.2.3 User alert filter configuration . . . . . . 6.4.2.4 Opslag . . . . . . . . . . . . . . . . . . . 6.5 Statement of work . . . . . . . . . . . . . . . . . . . . . 7 Componenten van de gebruikersapplicaties 7.1 De Alert Viewer . . . . . . . . . . . . . . . . 7.2 De Configuratie-editor . . . . . . . . . . . . 7.3 Integratie in Casmir . . . . . . . . . . . . . 7.3.1 App.structure . . . . . . . . . . . . . 7.3.2 Uitbreiding Casmir . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
Agent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . . . . . . . . .
. . . . . . . . . . .
. . . . .
. . . . . . . . . . . .
. . . . . . . . . . .
. . . . .
. . . . . . . . . . . .
. . . . . . . . . . .
. . . . .
. . . . . . . . . . . .
. . . . . . . . . . .
. . . . .
. . . . . . . . . . . .
25 25 27 29 30 30 31 32 36 36 37 38
. . . . . . . . . . .
39 39 39 40 40 41 43 43 46 49 49 50
. . . . .
52 52 54 56 57 59
Lijst van figuren
61
Literatuurlijst
63
Afbeeldingen van de applicaties
65
Codefragmenten
68
Hoofdstuk 1 Huidige Situatie en Probleemstelling 1.1
Algemeen
ICORDA is een bedrijf dat zich specialiseert in het beheren van hard- en software en het realiseren van ICT-projecten bij andere bedrijven. Deze masterproef zal handelen over het eerste, nl. het beheer van de hardware en de software. Elke klant van ICORDA heeft een server die de ICORDA Agent (IA) software draait. Dit serverprogramma haalt alle mogelijke gegevens op over de hardware en de software bij die klant. Zoals hiervoor vermeld, heeft elke klant een IA draaien die alle nodige gegevens ophaalt. Deze gegevens worden door het team van de Operations afdeling van ICORDA geanalyseerd. Op basis van hun analyse kunnen zij beslissen of een bepaalde waarde van een bepaalde categorie verontrustend is of niet. Wanneer zo’n situatie zich voordoet, zal een medewerker van ICORDA zelf proberen om het probleem op te lossen. Als dit niet mogelijk is, informeert de medewerker de klant over het probleem. Een voorbeeld: het zou kunnen dat een server bij de klant te weinig schijfruimte heeft om goed te kunnen functioneren. Wanneer een ICORDA-medewerker dit probleem ontdekt, dan zal die medewerker, mits toestemming van het bedrijf, dit proberen oplossen.
1.2
Opstelling
Bij de klant staat de server, voorzien van de IA-software, die de gegevens ophaalt. Deze gegevens worden dan naar de databank van ICORDA gestuurd. De gegevens worden binnengehaald door het programma Dashboard. Het programma Dashboard toont alle opgehaalde gegevens op een overzichtelijke manier aan de medewerker van ICORDA. Het is mogelijk om de databank vanuit Dashboard aan te vullen met extra gegevens. Het kan zijn dat de situatie bij de klant uitzonderlijk is waardoor er extra aandacht vereist is. Daarbij kunnen aanpassingen in de databank nodig zijn. Een ICORDA-medewerker analyseert de data die hij/zij ontvangt en wanneer hij/zij klaar is, kan het Remote Maintenance Report (RMR) worden aangemaakt. Het RMR bevat alle
1
Hoofdstuk 1. Huidige Situatie en Probleemstelling
2
informatie over wat er de afgelopen maand met de software en de hardware van die klant is gebeurd. Dit rapport wordt maandelijks opgesteld en wordt naar de klant gestuurd.
Figuur 1.1: Opstelling ICORDA en klanten
1.3
Probleemstelling
In de huidige situatie moet een medewerker van ICORDA de problemen zelf ontdekken. Er is geen systeem aanwezig om aan te geven dat er een probleem is bij een bepaalde klant. Daarom moet de informatie die afkomstig is van de ICORDA Agent manueel gecontroleerd worden. Wanneer de klant meerdere servers heeft, kan dit een grote opdracht worden waarbij gemakkelijk fouten kunnen gemaakt worden. Een ander probleem doet zich voor wanneer een probleem is opgelost. Het is in deze opstelling van hard- en software niet mogelijk om te weten of een probleem is opgelost of niet. Ook is het niet mogelijk om te weten of een probleem in behandeling is. In de huidige situatie moet hiervoor goed gecommuniceerd worden, wat niet altijd even evident is.
Hoofdstuk 2 Doelstelling In de situatie zoals die hiervoor werd ge¨ıllustreerd, wordt er niets gedaan met de informatie die door de IA in de databank werd toegevoegd. Deze informatie kan gebruikt worden om snel bepaalde problemen te ontdekken. Dit is dan ook het doel van deze masterproef. Er moet bij de huidige opstelling een Remote Controlled Alert & Task Agent bijkomen. Deze moet ervoor zorgen dat wanneer gegevens worden opgehaald ze onmiddellijk aan een analyse worden onderworpen. Op basis van de analyse kunnen bepaalde problemen worden vastgesteld. Naargelang de wens van de klant kan een waarschuwingsmail worden verstuurd naar een van de medewerkers van ICORDA. Er kan ook een andere actie ondernomen worden. De waarschuwingsmail is de minimumvereiste van het systeem. In dit systeem is het de taak van de medewerkers van ICORDA om de taken naar de wens van de klant te kunnen instellen. Het moet gemakkelijk zijn dit voor elke klant te kunnen opvragen en te kunnen veranderen indien nodig. Er zullen verschillende alarmtypes zijn en verschillende soorten taken/acties. Alarmen en taken moeten dynamisch kunnen ingesteld worden. Een taak moet met verschillende alarmen kunnen geassocieerd worden en omgekeerd. Het moet ook mogelijk zijn om voor een klant alarmen van hetzelfde type in te stellen (bv. gebruikte schijfruimte 90% en 95%). Alarmen kunnen ook een prioriteit hebben. Deze duidt aan hoe belangrijk het alarm voor de klant is en hoe snel het moet worden opgelost. Wanneer moet een alarm geactiveerd worden? In de meeste gevallen wordt een alarm geactiveerd wanneer een drempelwaarde voor een bepaalde categorie werd overschreden. Het zou ook kunnen dat een combinatie van waarden van bepaalde categorie¨en verontrustend is. Dan moet men deze natuurlijk samen controleren. Er kunnen verschillende redenen zijn waarom een alarm geactiveerd wordt. Uit deze beschrijving van de doelstelling volgen nog een tweetal bijkomende vereisten voor het systeem. Een eerste bijkomende vereiste van het systeem is dat een gebruiker snel moet kunnen weten of een andere gebruiker reeds met het probleem bezig is. Wanneer dit het geval is, kan ook nog vermeld worden welke persoon dit is. Een tweede vereiste is dat de configuratie snel moet kunnen gebeuren. Dit wil zeggen dat er een 3
Hoofdstuk 2. Doelstelling
4
soort van template zal zijn die de basisconfiguratie om een bepaalde alert te detecteren bevat. Het enige wat de gebruiker moet doen is de waarden invullen voor de eigenschappen van de alert. Daarnaast moet een gebruiker ook snel kunnen instellen wat hij/zij in de e-mail wil zien verschijnen, en uit een lijst van e-mailadressen kunnen kiezen om de verantwoordelijken op de hoogte te brengen. Nog eens samengevat moet de Remote Controlled Alert & Task Agent op een effici¨ente manier problemen bij bepaalde klanten kunnen ontdekken. Welke problemen voor welke klanten moeten gemeld worden, wordt vastgelegd in de configuratie. Deze configuratie moet op zo’n eenvoudig mogelijke manier kunnen opgesteld worden door de medewerkers van ICORDA. Als laatste moeten ook alle alerts op een overzichtelijke manier kunnen bekeken worden.
Hoofdstuk 3 Algemene Begrippen Dit hoofdstuk zal een kleine inleiding geven over wat de Remote Controlled Alert & Task Agent is. Er zullen een aantal begrippen aan bod komen, die verder in deze scriptie zullen worden gebruikt.
3.1
Alerts en Taken
Deze twee begrippen liggen aan de basis van deze masterproef. Bij elke alert hoort minstens een taak en bij elke taak hoort een alert. • Een alert zal worden gegenereerd wanneer er bepaalde voorwaarden zijn voldaan. Deze voorwaarden zullen een categorie bevatten (bv. harde schijf) en een subcategorie (bv. gebruikte schijfruimte). Soms kan ook een waarde (bv. 90% gebruikte schijfruimte) worden opgegeven, maar dat is niet altijd het geval. Een alert bevat genoeg informatie om te weten over welke klant het gaat, over welke machine van die klant het gaat en over welke categorie en subcategorie van die machine het gaat. • Een taak hoort bij een alert. Bij het genereren van een alert wordt ook een taak uitgevoerd. Zoals al eerder vermeld is dit standaard een e-mail versturen. Dit kan ook iets anders zijn. In het geval van een alert met harde schijf als categorie zou een taak gegevens die minder belangrijk zijn, kunnen overzetten naar een andere harde schijf.
3.2
Alert Filter en Alert Filter Extensie
• Een alert en een taak worden samengevoegd in een alert filter. Een alert filter bevat de voorwaarden die moeten voldaan zijn om een alert te genereren. Ook de configuratie voor de taak wordt hierin opgeslagen, m.a.w. het bevat de configuratie voor het versturen van de e-mail. Zowel naar wie de e-mail wordt verstuurd, als de inhoud van de e-mail wordt bewaard in de alert filter in de vorm van een taak. • Een alert filter extensie is een extra voorwaarde die kan gekoppeld worden aan de alert filter. Soms zijn er voorwaarden nodig die niet gebruikmaken van de 5
Hoofdstuk 3. Algemene Begrippen
6
standaard operatoren (=, < , > , . . . ) zoals het controleren of een waarde een aantal dagen dezelfde is gebleven, of bij een datum controleren hoe lang geleden die datum is. Meer uitleg hierover vind je in het volgende hoofdstuk.
3.3
Monitoring Facts
Monitoring Facts zijn de gegevens die moeten geanalyseerd worden. Ze worden aangeleverd door de IA en bevatten informatie over de opstelling bij een van de klanten van ICORDA. De IA maakt monitoring facts aan om de huidige situatie bij de klant te schetsen. Ze kunnen bijvoorbeeld aangeven wanneer de laatste update van de anti-malware software is gebeurd of hoeveel keer een back-up niet gelukt is, onderbroken werd of wel gelukt is. Uit de monitoring facts kan worden afgeleid of er een alert moet worden gegenereerd. De waarden die in de monitoring fact zijn opgeslagen kunnen worden vergeleken met de voorwaarden die in de alert filter zijn opgeslagen. Voldoen deze waarden, dan zal een alert worden aangemaakt en zal de bijhorende taak worden uitgevoerd.
3.4
De Alert & Task Agent
Wat de Alert & Task Agent nu moet doen, is de monitoring facts, die afkomstig zijn uit de databank, analyseren. Op basis van de analyse moet hij beslissen of de opgehaalde gegevens als alarmerend moeten beschouwd worden. Is het antwoord ja, dan zal de Alert & Task Agent een alert genereren en de bijhorende taak uitvoeren. De analyse maakt gebruik van de alert filters om te bepalen of monitoring facts als alarmerend moeten worden beschouwd. De alert filters moeten natuurlijk ergens kunnen aangemaakt worden. Dit zal gebeuren aan de hand van een applicatie die de configuratie op elk moment kan aanpassen. De configuratie moet toelaten om voor elke klant apart te kunnen bepalen welke alerts er moeten gegenereerd worden. Dit is de algemene configuratie. Daarnaast moet elke gebruiker de algemene configuratie naar zijn hand kunnen zetten zonder dat de algemene configuratie wordt aangepast. Dit wil zeggen dat die gebruiker kan bepalen of hij/zij bijvoorbeeld geen alerts wil ontvangen van bepaalde zaken, of dat hij/zij voor een bepaalde alert strengere voorwaarden wil opleggen. De configuratie-applicatie moet er dus voor zorgen dat de configuratie voor elke klant kan ingesteld worden, en dat elke gebruiker die configuratie voor zichzelf nog kan aanpassen.
Hoofdstuk 3. Algemene Begrippen
7
Om het opzoeken van alerts te vereenvoudigen zal een aparte applicatie alle alerts onderverdelen per klant, per machine van de klant en per categorie van die machine. Zo kan elke gebruiker snel de alerts bekijken die voor een bepaalde klant zijn aangemaakt. In deze applicatie zal het dus mogelijk zijn om de informatie die bij de alerts horen te bekijken. De applicatie zal ook toelaten om alerts toe te kennen aan medewerkers om het probleem, dat aan de alert is gekoppeld, op te lossen.
Hoofdstuk 4 Het Model In het vorige hoofdstuk werden al enkele begrippen uitgelegd die aan de basis liggen van deze masterproef. In dit hoofdstuk zullen deze begrippen verder aan bod komen in het model. Het model bestaat uit drie delen: • Het eerste deel bestaat uit de gegevens die moeten geanalyseerd worden. De hoofdrolspeler is hier de monitoring fact. Er zijn nog een aantal extra gegevens, zoals de klantgegevens en de machinegegevens, die kunnen gebruikt worden bij de analyse. • Het tweede deel is de configuratie. Hier zal het voornamelijk over de alert filters en de alert filter extensies gaan. Daarnaast worden er nog een aantal klassen voorzien om de configuratie bij te houden en aan te passen. • Het laatste deel van het model dient voor het beheer van de alerts.
4.1 4.1.1
Het Model in detail De Analysegegevens
De monitoring facts komen uit de databank die opgevuld wordt door de IA’s die bij de klanten zijn ge¨ınstalleerd. De databank bevat drie tabellen: een voor de monitoring facts, een voor de klantgegevens en een laatste voor de machinegegevens. De monitoring fact tabel bevat een verwijzing naar de klant, de machine, het onderdeel van de machine en eventueel nog een aantal subcategorie¨en van dat onderdeel.
Figuur 4.1: Associatie MonitoringFact en Repertor
8
Hoofdstuk 4. Het Model
9
De klassenstructuur die hiervoor wordt gebruikt is niet zelf aangemaakt, maar wordt gegenereerd. Hiervoor wordt het ADO Entity Framework gebruikt, dat alle tabellen en referenties naar andere tabellen kan omzetten naar klassen en associaties tussen klassen. Voor meer uitleg hierover verwijzen we naar hoofdstuk 5.
4.1.2
De Configuratie
De configuratie wordt ook opgeslagen in de databank, maar het kan ook uit een XML-bestand komen. Hiervoor wordt de interface IAlertFilterConfiguration gebruikt die vastlegt welke properties en methoden er nodig zijn om de nodige gegevens op te halen. Dan zijn er twee implementaties voorzien, een voor het gebruik van een databank en een voor het gebruik van een XML-bestand. De XmlAlertFilterConfiguration klasse werd eerst gebruikt omdat de structuur van de configuratie geregeld werd aangepast. Door met een XML-bestand te werken kon de configuratie eenvoudiger aangepast worden. In tegenstelling tot een databank kon het XML-bestand telkens verwijderd worden zodat de nieuwe configuratie kon gegenereerd worden in een nieuw XML-bestand. Met een databank zou deze taak veel moeilijker geweest zijn, omdat er rekening moet worden gehouden met relaties tussen verschillende tabellen, verplichte velden van een tabel en eventueel nog andere beperkingen. Een simpel voorbeeld hiervan is het toevoegen van een nieuw verplicht veld in een bepaalde tabel. Dan is het niet mogelijk om de tabel aan te passen, de tabel moet verwijderd worden en terug aangemaakt worden. Het verwijderen van een tabel kan dan nog een extra probleem opleveren: een andere tabel kan afhankelijk zijn van de te verwijderen tabel, waardoor de huidige tabel niet kan worden verwijderd. Daarom is de AlertFilterConfiguration klasse, die gebruikmaakt van de databank, op het einde van de masterproef aangemaakt.
4.1.2.1
General Alert Filters
De configuratie bestaat hoofdzakelijk uit objecten van de GeneralAlertFilter klasse die is afgeleid van de abstracte AlertFilter klasse die op haar beurt de IAlertFilter interface implementeert. De AlertFilter klasse implementeert een gedeelte van de interface en de rest wordt ge¨ımplementeerd door de concrete klassen. Een alert filter legt vast van welke monitoring facts alerts moeten worden gegenereerd. In de alert filter wordt er een filter string opgeslagen om te weten voor welke monitoring facts alerts moeten worden aangemaakt. Deze filter string wordt at runtime omgezet naar objecten met de ConvertToCriteriaOperator() methode. Het object dat hieruit voortkomt wordt dan gebruikt om een query uit te voeren op de opgehaalde monitoring facts (dit wordt verder behandeld in 4.2). De RepertorID duidt aan op welke klant de alert filter van toepassing
Hoofdstuk 4. Het Model
10
is. De IsCritical property wordt gebruikt om het verschil aan te duiden tussen critical alerts en gewone alerts. Wanneer deze true is wil dit zeggen dat de alerts, die door deze alert filter werden aangemaakt, zo snel mogelijk moeten onderzocht worden. Een alert filter heeft ook een lijst van taken die het moet laten uitvoeren als er een alert wordt gegenereerd. 4.1.2.2
User Alert Filters
Om toe te laten dat een gebruiker van de configuratie-applicatie zijn eigen configuratie kan samenstellen, is er nog een extra klasse nodig. De UserAlertFilter klasse, die ook is afgeleid van de abstracte AlertFilter klasse, zal hiervoor zorgen. Deze klasse bevat dus dezelfde eigenschappen als de GeneralAlertFilter klasse, maar heeft nog twee extra properties. De eerste property duidt aan welke gebruiker deze user alert filter heeft aangemaakt en de tweede property duidt aan of de gebruiker notificaties wil ontvangen voor deze alert filter. Hoe wordt een user alert filter aan een algemene alert filter gelinkt? In de GeneralAlertFilter klasse wordt een collectie van UserAlertFilter objecten bijgehouden. Dit wil zeggen dat wanneer een gebruiker de algemene configuratie wil aanpassen, er een UserAlertFilter object zal worden aangemaakt met die aangepaste configuratie. Het UserAlertFilter object zal dan worden toegevoegd aan de collectie van UserAlertFilter objecten in het GeneralAlertFilter object. Ook wanneer de gebruiker geen alerts wil ontvangen voor een bepaalde alert filter, wordt er een user alert filter aangemaakt die dit aanduidt. Als een bepaalde gebruiker geen eigen configuratie heeft aangemaakt voor een alert filter, dan wordt er van uit gegaan dat deze gebruiker alerts wil ontvangen voor de alert filter. Als de gebruiker wel een user alert filter aanmaakt voor een alert filter, dan wordt hij ook uit de lijst van ontvangers gehaald van de e-mail voor de algemene alert filter. Op deze manier kan de algemene configuratie behouden blijven en kan elke gebruiker de configuratie naar eigen behoefte aanpassen.
Hoofdstuk 4. Het Model
11
Figuur 4.2: Klassenhi¨erarchie alert filters
4.1.2.3
Alert Filter Extensies
Elke alert filter kan ook een alert filter extensie bevatten. Een alert filter extensie is afgeleid van de abstract klasse AlertFilterExtension die de IAlertFilterExtension interface implementeert. Een alert filter extensie zal voor een extra controle zorgen op de monitoring fact. Dit is nodig voor alerts waar de filter string niet alle voorwaarden kan bevatten. Dit is een gevolg van de beperkingen van de control in de configuratie-applicatie die gebruikt wordt om de filter string aan te maken. Dit wordt verder besproken in hoofdstuk 6. In figuur 4.3 zijn er drie extensies te zien: • De DateTimeFilterExtension verwacht dat de value van de monitoring fact een datum met tijdsaanduiding is. Zo kan er ook op datum gecontroleerd worden. • De EqualForDaysFilterExtension controleert of de value van de monitoring fact dezelfde is gebleven voor een aantal dagen. Dit is vooral handig als de value property van de monitoring fact een bepaalde waarde heeft die niet veel verandert. Als er dan moet gecontroleerd worden of deze waarde te lang ongewijzigd is gebleven, kan deze alert filter extensie gebruikt worden. • De NumberRegexFilterExtension wordt gebruikt om een formaat zoals tijdsaanduiding te kunnen parsen a.d.h.v. een reguliere expressie. Daarvoor wordt
Hoofdstuk 4. Het Model
12
de IFormatRegex interface gebruikt. Deze interface voorziet een methode die controleert of de waarde van de monitoring fact voldoet aan de reguliere expressie. Als de waarde voldoet aan de reguliere expressie, wordt een getal teruggegeven door de methode. De abstracte FormatRegex klasse implementeert deze interface. Er zijn twee klassen die overerven van de FormatRegex klasse: – Bij de TimeSpanRegex klasse worden de uren en de minuten die in de string aanwezig zijn, omgezet naar minuten. Dit wordt gebruikt om te weten hoelang de uninterruptible power supply1 (UPS) nog mee kan. – Bij de CountRegex wordt er een getal uit de string gehaald. Dit getal wordt dan gebruikt om te vergelijken met een door de gebruiker ingesteld getal. Daarvoor kunnen de standaard vergelijkingsoperatoren gebruikt worden. Met deze klasse is het mogelijk om na te kijken hoeveel keer een back-up succesvol is afgerond.
Figuur 4.3: Klassenhi¨erachie alert filter extensies 1
UPS wordt gebruikt om stroom te voorzien aan de belangrijkste apparaten wanneer de stroom wegvalt.
Hoofdstuk 4. Het Model 4.1.2.4
13
Task klassen
De taken leggen vast wat er moet gebeuren wanneer er een alert wordt gegenereerd. Daarom heeft elke alert filter een collectie Task objecten. De Task klasse implementeert de ITask interface die een methode bevat, die de taak uitvoert. In het geval van de EmailTask is dat een e-mail versturen door gebruik te maken van de MailConfiguration klasse. Deze klasse bevat alle informatie om de e-mail naar de juiste personen te sturen met alle informatie over de alert. De e-mail kan ook mogelijke oplossingen bevatten voor het probleem.
Figuur 4.4: Klassenschema voor taken
Met deze klassenhi¨erarchie kunnen er in de toekomst eenvoudig extra taken toegevoegd worden door gebruik te maken van de abstracte Task klasse. Om de nieuwe taken in de databank op te slaan kan er gebruikgemaakt worden van Entity Framework Code first (zie 5.1.3.2 in hoofdstuk 5). 4.1.2.5
Overzicht
In figuur 4.5 wordt het volledige klassenschema van de configuratie getoond. In het schema is duidelijk zichtbaar dat er eenvoudig kan uitgebreid worden. Er zou nog een AlertFilter klasse kunnen bijkomen zonder dat de alert filter configuration klassen hiervoor moeten worden aangepast. Ook de AlertFilterExtension klassen kunnen uitgebreid worden en idem voor de FormatRegex klassen en de Task klassen. Zolang er van een interface of een abstracte klasse wordt gebruikgemaakt kan de volledige configuratie uitgebreid worden. Waarom de AlertFilter klasse, de AlertFilterExtension klasse en de NumberRegexFilterExtension klassen gebruikmaken van de abstracte klassen in plaats van de interface wordt verduidelijkt in 5.1.3.2 in hoofdstuk 5.
Hoofdstuk 4. Het Model
14
Figuur 4.5: Klassenschema alert filter configuratie
In de voorgaande figuur is ook de FactsChecker klasse te zien. Deze klasse voert de analyse van de monitoring facts periodiek uit. Hoeveel tijd er tussen twee analyses zit, wordt aangeduid door de PollingInterval property. De IFactCheckerContext interface zal in 4.1.3 worden verduidelijkt.
4.1.3
De Alerts
Wanneer de alert filters uit de vorige paragraaf ervoor zorgen dat er alerts worden gegenereerd, dan zijn deze alert objecten van de klasse MonitoringFactAlert. Deze klasse bevat een verwijzing naar de monitorig fact waarvoor de alert is aangemaakt en een verwijzing naar de alert filter waardoor de alert is aangemaakt. De UserAlertFilterUserID property geeft aan voor wie de alert is aangemaakt. Het was dus een user alert filter die ervoor gezorgd heeft dat de alert is aangemaakt. De Subject en Body property bevatten de inhoud van de e-mail die is verstuurd. IsCritical geeft aan of het een belangrijke alert is. De twee laatste properties dienen om de alert toe te kennen
Hoofdstuk 4. Het Model
15
aan een medewerker van ICORDA. De InitialenCode geeft aan wie die persoon is en Solved duidt aan of het probleem is opgelost.
Figuur 4.6: Structuur gegenereerde alerts
De MonitoringFactAlert objecten worden ook opgeslagen in de databank, maar zouden ook naar een XML-bestand kunnen weggeschreven worden. Hiervoor wordt weer gebruikgemaakt van een interface, nl. de IFactCheckerContext. Deze interface legt de methoden voor het ophalen, toevoegen en verwijderen van alerts vast. Zo hebben de XmlFactsCheckerContext en de FactsCheckerContext dezelfde functionaliteit, maar gebruiken ze een andere databron, respectievelijk een XML-bestand of de databank. Omdat men moet weten of een alert reeds gegenereerd is of niet, moet een alert uniek ge¨ıdentificeerd kunnen worden. Hiervoor maken we gebruik van de FactsCheckerContext klasse. Deze klasse heeft als enige doel, de gegenereerde alert bijhouden. Om elke alert uniek te kunnen identificeren, maken we gebruik van een hash set. Een hash set is te vergelijken met een gewone array waar de indexering van de elementen anders is. Voor een object wordt toegevoegd, wordt een hashwaarde2 van dat object berekend. Deze hashwaarde zal dienen als index voor de set. Als er nog geen object aanwezig is op die index, kan er veilig vanuit gegaan worden dat er nog geen alert is gegenereerd. De alert kan dus toegevoegd worden. Op deze manier is elke record in de databank uniek, en bij het herstarten van de service moet gewoon elke record uit de databank worden gehaald. Zo voegen we niet twee keer dezelfde alert toe aan de databank. 2
hashwaarde: Dit is een getal dat berekend wordt aan de hand van een aantal eigenschappen van het object. Voor elke uniek object wordt er een unieke hashwaarde gegenereerd.
Hoofdstuk 4. Het Model
16
De standaard berekening van de hashwaarde in C# is niet goed genoeg om alerts uniek te kunnen identificeren. Normaal gaat C# er van uit dat elk verschillend object ook een verschillende hashwaarde moet opleveren. Voor een alert is dit niet zo. Een alert moet pas gegenereerd worden als de eigenschappen van de monitoring fact verschillen en als de klant ID verschillend is. Om te weten om welke alert het gaat, wordt de alert filter ID gecontroleerd die bij de alert wordt opgeslagen. Om het probleem met de hashwaarde op te lossen gebruiken we de interface IEqualityComparer. Deze interface wordt gebruikt door de hash set om de hashwaarde te berekenen en om te controleren of objecten wel degelijk gelijk zijn aan elkaar. Met deze interface hebben we ervoor gezorgd dat verschillende alert objecten toch gelijk kunnen zijn als ze dezelfde eigenschappen hebben. In het volgende voorbeeld staat dit ge¨ıllustreerd. Listing 4.1: Voorbeeld van custom comparer voor HashSet 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
public class FactComparer : IEqualityComparer < MonitoringFactAlert > { public bool Equals ( M on i t or i n gF a c tA l e rt mfa1 , M on i t or i n gF a c tA l e rt mfa2 ) { MonitoringFact f1 = mfa1 . MonitoringFact ; MonitoringFact f2 = mfa2 . MonitoringFact ; bool equal = f1 . RepertorID == f2 . RepertorID && f1 . Category . Equals ( f2 . Category ) && f1 . Product . Equals ( f2 . Product ) && mfa1 . AlertFilterID == mfa2 . AlertFilterID ; if ( f1 . GroupTag != null && f2 . GroupTag != null ) { equal = equal && f1 . GroupTag . Equals ( f2 . GroupTag ) ; } if ( f1 . SubGroupTag != null && f2 . SubGroupTag != null ) { equal = equal && f1 . SubGroupTag . Equals ( f2 . SubGroupTag ) ; } return equal ; } public int GetHashCode ( M on i t or i n gF a c tA l e rt alert ) { int hash = ( int ) ( alert . MonitoringFact . RepertorID + alert . MonitoringFact . Product . GetHashCode () + alert . MonitoringFact . Category . GetHashCode () ) + alert . AlertFilterID ; if ( alert . MonitoringFact . GroupTag != null ) {
Hoofdstuk 4. Het Model 31 32 33 34 35 36 37 38 39 40
17
hash += alert . MonitoringFact . GroupTag . GetHashCode () ; } if ( alert . MonitoringFact . SubGroupTag != null ) { hash += alert . MonitoringFact . SubGroupTag . GetHashCode () ; } return hash ; } }
4.2
Algoritme voor de Analyse van Monitoring Facts
Het algoritme dat gebruikt wordt is een opeenvolging van ophaalinstructies of (LINQ3 ) query’s en testen die ervoor zorgen dat het algoritme sneller wordt. De eerste query die wordt uitgevoerd, is deze die controleert of er nieuwe monitoring facts zijn toegevoegd sinds de laatste keer dat het algoritme succesvol werd uitgevoerd. Wanneer er nieuwe monitoring facts zijn toegevoegd worden deze opgehaald. Voor de controle of er monitoring facts zijn en het ophalen van de monitoring facts wordt de query een keer uitgevoerd. Voor de controle moet de query niet uitgevoerd worden, omdat LINQ hiervoor een methode gebruikt die aangeeft of er een object is. Voor het ophalen van de monitoring facts wordt de query wel uitgevoerd. In de volgende stap van het algoritme wordt elke alert filter uit de configuratie ingelezen. In deze lijst van alert filters zitten de algemene alert filters en de user alert filters. Elke alert filter wordt gebruikt om te controleren of er monitoring facts zijn waarvoor er een alert moet gegenereerd worden. Het is de filter string die is opgeslagen in de alert filter die dit bepaalt. Als een monitoring fact object voldoet aan de voorwaarden die in de filter string zijn gedefini¨eerd, komt het in aanmerking om er een alert voor aan te maken. Voor de controle wordt de filter string omgezet naar een CriteriaOperator object met de methode ConvertToCriteriaOperator. Dit object kan dan vervolgens omgezet worden naar een where clausule van een LINQ-query (zie hoofdstuk 5). Als het resultaat van de tweede query objecten bevat dan moeten we controleren of er voor deze overblijvende monitoring facts al alerts zijn gegenereerd. Dit doen we door voor elke monitoring fact een MonitoringFactAlert object aan te maken, en vervolgens gebruik te maken van een hash set (zie vorige paragraaf) die alle unieke alerts bijhoudt. 3
Een querytaal zoals SQL, maar dan voor .NET programma’s. Voor meer informatie zie hoofdstuk 5
Hoofdstuk 4. Het Model
18
Deze hash set wordt bijgehouden door de FactsCheckerContext klasse. Nu kunnen we het aangemaakte MonitoringFactAlert object gebruiken om te controleren of er al een alert in de hash set zit met dezelfde eigenschappen. Kan zo’n alert niet gevonden worden in de lijst, dan moeten we hem toevoegen en de bijhorende taken uitvoeren. De standaard taak is altijd een e-mail versturen. Hier moet het algoritme er ook voor zorgen dat er enkel e-mails worden verstuurd naar de personen die dit willen. Als het over een gewone alert filter gaat, sturen we e-mails naar de personen die geen user alert filter hebben gedefini¨eerd, want de user alert filters zullen later nog gecontroleerd worden, of zijn al gecontroleerd. Als het een user alert filter is moeten we enkel een e-mail sturen naar de persoon die de user alert filter heeft aangemaakt. Volgende pseudocode geeft de structuur van de code weer: Listing 4.2: Structuur algoritme voor analyse van opgehaalde facts 1 2 3 4 5 6
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
void DoPoll () { if (! actionRunning ) { actionRunning = true ; var factsQuery = DataService . GetMonitoringFactsWithDateTimeGreaterThen ( DateOfLastSuccessfullPoll ); if ( factsQuery bevat objecten ) { // Query wordt hier uitgevoerd var factsList = factsQuery . ToList () ; var queryDate = DateTime . Now ; // Alle ingestelde filters overlopen // zowel AlertFilter als UserAlertFilters worden hier opgehaald foreach ( var alertFilter in AlertFilters ) { // Check op alerts ( LINQ ) var filterQuery = from fact in factsList select fact ; // FilterString converteren naar object var criteriaOperator = alertFilter . C o n v e r t T o C r i t e r i a O p e r a t o r () ; // Object gebruiken om de query uit te breiden met een LINQ where clausule var filteredData = C o n v e r t C r i t e r i a O p e r a t o r T o L i n q W h e r e C l a u s e ( criteriaOperator , filterQuery ) ; if ( filteredData bevat objecten ) { foreach ( var f in filteredData ) { var alert = context . C r e a t e M o n i t o r i n g F a c t A l e r t (f , alertFilter ); // Wanneer de Fact kan toegevoegd worden , wordt hij ook in
Hoofdstuk 4. Het Model de databank toegevoegd . // Controle voor eventuele filter extensies en of de alert al bestaat if ( alertFilter . S ho u l dG e n er a t eA l e rt ( f ) && ! context . C o n t a i n s M o n i t o r i n g F a c t W i t h A l e r t ( alert ) ) { context . A d d M o n i t o r i n g F a c t A l e r t ( alert ) ; foreach ( var task in alertFilter . Tasks ) { task . execute ( f ) ; } }
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
} } } context . LastSuccess = queryDate ; } else { context . LastSuccess = DateTime . Now ; } actionRunning = false ; } }
19
Hoofdstuk 5 Gebruikte technologie¨ en In dit hoofdstuk komen alle technologie¨en, bibliotheken en design patterns aan bod die gebruikt zijn om de verschillende applicaties te kunnen ontwikkelen.
5.1
ADO Entity Framework
Het ADO Entity Framework is een andere manier om vanuit een programma met een databank te communiceren. Voor elke tabel die je wil gebruiken maak je een eniteit aan. Deze entiteit is een klasse waarbij de properties van de klasse op de kolommen van de tabel worden gemapt. Op die manier moet je geen conversie meer voorzien tussen objecten van het model en objecten die je terugkrijgt als resultaat van een query.
5.1.1
Entity Datamodel
Het entity datamodel bestaat uit drie delen: • Het conceptueel model geeft aan hoe de klassen zullen gestructureerd zijn. Het duidt aan welke associaties er gelegd worden en welke eigenschappen de klasse zal hebben. Dit model kan verschillen van het databankmodel. • Het opslagmodel is hetzelfde maar dan voor de databank. Het zal dus alle tabellen, views, stored procedures en de relaties tussen de tabellen bevatten. • De mapping bepaald hoe het conceptueel model wordt afgebeeld op het opslagmodel. Bv: Als er een relatie is tussen twee tabellen, zal er ook een associatie zijn tussen de twee klassen die de twee tabellen voorstellen in het programma.
5.1.2
Communicatie met de databank
De communicatie tussen programma en databank gebeurt in vier stappen: 1. De programmeur zal ofwel gebruikmaken van LINQ to Entities of Entity SQL om data te kunnen opvragen van de databank. Het zijn beide query talen die toelaten vanuit het programma gegevens op te vragen uit de databank. 20
Hoofdstuk 5. Gebruikte technologie¨en
21
2. Wanneer de programmeur zijn query heeft geschreven, zal de Object Services laag ervoor zorgen dat de query (in zijn oorspronkelijke vorm) wordt doorgegeven aan de volgende laag. Bij het ontvangen van het antwoord op deze query zal de Object Services laag voor de conversie naar entiteitobjecten zorgen. 3. De Entity Client Data Provider (ECDP) zal de query van LINQ to Entities of Entity SQL omzetten naar (normale) SQL. De SQL-query wordt dan doorgegeven aan de volgende laag. 4. De ADO.NET Data Provider zorgt voor de communicatie met de databank. ADO.NET is een standaard manier om vanuit een .NET-programma te communiceren met een databank. Het zorgt voor de connectie met de server en het uitvoeren van de gespecificeerde query. Het resultaat komt dan in een data set terecht die alle tabellen met bijhorende velden bevat.
Figuur 5.1: ADO Entity Framework lagenmodel
Hoofdstuk 5. Gebruikte technologie¨en
5.1.3
22
Gebruik
Omdat het gebruik van ADO Entity Framework rechtstreeks is ge¨ıntegreerd in Visual Studio is het heel gemakkelijk in gebruik te nemen. Je kan ervoor kiezen om eerst de databank op te stellen en op basis hiervan het model te laten genereren. Of je kan eerst het model aanmaken en de databank op basis van het model laten genereren. Beide opties bieden dezelfde mogelijkheden. De programmeur moet zelf kiezen wat hem/haar het beste uitkomt. 5.1.3.1
Databank eerst
Wanneer de databank reeds bestaat kan je het model automatisch laten genereren. Dit doe je door aan je Visual Studio project een entity data model toe te voegen. Je moet het entity data model dan baseren op een bestaande databank. Dit doe je door met de juiste databankserver te connecteren en vervolgens de tabellen, views, stored procedures,. . . te kiezen die je wil gebruiken in je programma. Als je dit hebt gedaan zal het ADO Entity Framework een entity data model genereren. Het entity data model is een bestand dat alle klassen bevat, vastlegt hoe die klassen moeten gemapt worden op tabellen in de databank en toegang tot de databank biedt via een klasse die is afgeleid van de ObjectContext klasse. De ObjectContext klasse bevat alle nodige implementaties om te kunnen communiceren met een databank. Via het app.config of web.config configuratiebestand zal een ObjectContext object weten welke databank moet worden aangesproken. De klasse die is afgeleid van de ObjectContext klasse bevat voor elke entiteit een ObjectSet object (een property) die een van de entiteiten kan bevatten. Dit ObjectContext object wordt pas opgevuld wanneer ernaar gevraagd wordt in het programma. Dit wordt ook lazy loading genoemd. Wanneer je in je programma een bepaalde entiteit wil opvragen, maak je gebruik van een van de ObjectSet properties van de klasse die overerft van ObjectContext. Wanneer tabellen verwijzen naar elkaar met foreign keys 1 zal dit worden vertaald naar een associatie tussen klassen. Ook bij associaties wordt gebruikgemaakt van lazy loading. Een entiteit die bij een andere entiteit hoort wordt pas opgehaald als ernaar gevraagd wordt. 1
foreign key: een kolom van een tabel die records aanduidt van een andere tabel. Deze sleutel duidt aan dat de records uit de ene tabel en de andere tabel samen horen.
Hoofdstuk 5. Gebruikte technologie¨en
23
Figuur 5.2: Structuur entity data model
Deze manier van werken heeft als voordeel dat het model snel kan worden aangepast als de structuur van de databank of het opslagmodel wordt aangepast. Je kan het model opnieuw laten genereren met enkele klikken. Een ander klein voordeel is dat ook de databank kan aangepast worden door het model aan te passen. Dit is een klein voordeel omdat dit ervoor zorgt dat de bestaande tabellen eerst worden verwijderd om ze dan terug aan te maken. Dit is dus niet bruikbaar waarbij verlies van gegevens geen optie is. Het nadeel van deze methode is dat alles wordt gegenereerd en dus niet aanpasbaar is. Elke aanpassing wordt bij de volgende update van het model overschreven. Je kan dit wel omzeilen door gebruik te maken van parti¨ele klassen. Dit zijn klassen die over meerdere .cs-bestanden zijn verdeeld. Een deel wordt dan aangemaakt door de codegeneratie en een ander deel wordt manueel aangemaakt. 5.1.3.2
Code eerst
Het is ook mogelijk om te vertrekken van het model om de databank aan te maken. Hierbij kan je weer gebruikmaken van een entity data model. Je moet dan een leeg entity data model aanmaken en de klassen hieraan toevoegen. Dan kan je de databank op dezelfde manier als hiervoor (tweede voordeel) laten genereren. Je kan er ook voor kiezen om alles manueel te doen. Je moet je wel houden aan bepaalde conventies om de modelklassen aan te maken. Bijvoorbeeld om een associatie tussen klassen te vertalen naar relaties tussen tabellen moet je ervoor zorgen dat de property voor deze associatie kan overschreven worden, ze moet dus met het virtual sleutelwoord zijn gemarkeerd. Ook bij overerving is er een kleine beperking: overerving kan enkel naar tabellen vertaald worden als er niet van interfaces wordt gebruikgemaakt. Dit is ook de reden waarom in het model van de configuratie elke interface door een abstracte klasse wordt ge¨ımplementeerd en niet door concrete klassen. Daarnaast moet je een klasse aanmaken die overerft van DbContext en alle DbSet properties toevoegen die verschillende entiteiten zullen bevatten. De DbContext klasse en de DbSet klasse zijn equivalent aan de ObjectContext klasse en de ObjectSet klasse die bij databank eerst worden gebruikt. Als het model is gecodeerd kan het in de databank worden aangemaakt door het programma te starten en een object van de DbContext klasse aan te maken.
Hoofdstuk 5. Gebruikte technologie¨en
24
Om het gedrag van het ADO Entity Framework aan te passen kan je gebruikmaken van C#-attributen. Deze attributen kunnen bijvoorbeeld de kolomnaam in een tabel aanpassen voor een property in een klasse, primary of foreign keys vastleggen in de klasse, een 1-op-veel relatie vastleggen tussen klassen en de overeenkomstige tabellen,. . . Naast de attributen om de configuratie aan te passen kan je ook gebruikmaken van klassen die hetzelfde werk samenbundelen. Dit wordt ook de Fluent API Mapping genoemd. Op deze manier kan je voor elke klasse/tabel een klasse aanmaken die vastlegt hoe de klasse op tabel moet worden gemapt. Je hebt bij deze manier van werken duidelijk meer controle over hoe de databank wordt aangemaakt, maar je kan niet gebruikmaken van de handige tools die bij een entity data model kunnen worden gebruikt. Het is ook eenvoudiger om de databank aan te passen als je op deze manier werkt. Elke aanpassing aan het model kan worden doorgevoerd naar de databank zonder ze eerst te moeten verwijderen en terug aan te maken. Je kan er wel voor kiezen dat de databank elke keer als ze aangepast wordt, volledig wordt afgebroken om ze daarna met de nieuwe configuratie terug op te bouwen. Hiervoor moet je gebruikmaken van de Package Manager Console van Visual Studio. Het laat toe een aantal commando’s te gebruiken die toelaten de aanpassingen aan het model te structureren. Elke aanpassing wordt opgeslagen in een klasse die is afgeleid van DbMigration. Deze klasse laat toe om de databank te upgraden (methode Up()) als te downgraden (methode Down()). Je hebt ook de keuze om de configuratie automatisch te laten doorvoeren naar de databank, maar dan heb je geen klassen waar je de aanpassingen kan bekijken. De stappen die je moet volgen om de databank aan te passen zijn: 1. In de Package Manager Console het commando Enable-Migrations uitvoeren. Dit commando gaat ervoor zorgen dat er een configuratieklasse en een initialisatieklasse wordt gegenereerd. De configuratieklasse bevat de instellingen die zullen gebruikt worden bij het upgraden van de databank. De initialisatieklasse zal zorgen voor het aanmaken van de databank als deze nog niet zou bestaan. 2. Als het model is aangepast, moet je dit eerst vastleggen in een DBMigration klasse. Deze klasse kan je laten genereren met het commando Add-Migration. Deze klasse bevat de code die nodig is om de databank aan te passen. 3. Met het commando Update-Database kan je de databank aanpassen. Dit commando zal dus nakijken welke versie het model er wordt gebruikt in de databank, en dan alle Up- of Down-methoden van alle DBMigration klassen uitvoeren totdat de gewenste versie is bereikt in de databank.
Hoofdstuk 5. Gebruikte technologie¨en 5.1.3.3
25
Implementatie
De beste implementatietechniek om te werken met de klasse die overerft van ObjectContext of DbContext is een singletonklasse2 aanmaken. Deze singletonklasse zal ervoor zorgen dat er maar een instantie van de DbContext klasse aanwezig is in het programma. De singletonklasse is dan ook best statisch zodat ze vanuit het hele programma gemakkelijk bereikbaar is. Je moet hiermee wel opletten, want dit wil ook zeggen dat verschillende threads op hetzelfde moment kunnen gebruikmaken van dezelfde DbContext. Je moet er dus ook voor zorgen dat de klasse thread safe is, door een slot op het DbContext object te zetten als het in gebruik is. Zo kan er slechts een thread tegelijk gebruikmaken van het DbContext object.
5.2
Het OData protocol
Het OData protocol is een combinatie van de twee dingen. Het ADO Entity Framework en een Windows Communication Foundation (WCF) data service. Het eerste dient om de data te voorzien zoals hiervoor werd besproken. Het tweede dient om een web service aan te maken, die toelaat dat andere programma’s kunnen gebruikmaken van dezelfde data. Het maakt gebruik van URI’s3 om gegevens op te halen, aan te passen of te verwijderen. Hiervoor worden de standaard HTTP-methoden GET, POST, PUT en DELETE gebruikt.
5.2.1
Gebruik en Werking
OData is een web service die met een databron is geconnecteerd. Daarom is het handig om in Visual Studio voor een leeg web project te kiezen. Het heeft enkel een web.config bestand nodig om te kunnen starten. De eerste stap is het aanmaken van de databron. Dit kan een door ADO Entity Framework gegenereerde klasse zijn, maar dit is niet noodzakelijk. Het kan een andere technologie zijn of een zelfgemaakte klasse. Het enige wat de databron moet hebben zijn een aantal properties die gegevens kan opvragen van een bepaalde databron. Vervolgens moet er een web service aangemaakt worden. Aangezien de web service enkel zal dienen om data door te sturen naar een programma of de databron, zal het een data web service zijn. Ook dit is in Visual Studio standaard aanwezig onder de vorm van een 2
Singletonklasse: Een klasse die ervoor zorgt dat er maar een instantie bestaat van een bepaalde klasse in heel het programma. 3 Uniform Resource Identifiers
Hoofdstuk 5. Gebruikte technologie¨en
26
WCF Data Service. Bij het aanmaken wordt er een nieuwe klasse aangemaakt die zal dienen voor de configuratie van de web service. Dit houdt in dat je moet zeggen welke databron er moet gebruikt worden, welke toegang er tot de databron is toegelaten, wat er moet gebeuren bij het opstarten enz. Om nu de web service te kunnen gebruiken in andere programma’s moet je twee dingen hebben. Je moet de URI kennen van de web service, en daarnaast moet je de klasse kennen die toegang biedt tot de databron, in dit geval een klasse die het volledige entity data model voorstelt. In een clientprogramma maak je gebruik van de entity data model klasse, maar je maakt een object aan door de URI van de web service mee te geven aan de constructor. Met de constructor doe je een aanvraag naar de web service om te kunnen gebruikmaken van de data die het voorziet. Vanaf nu kan je gebruikmaken van de entiteitklassen om data op te vragen of op te slaan. In het volgende voorbeeld kan je zien hoe een WCF Data Service klasse er uitziet. Deze klasse heeft standaard een methode die aangeeft hoe je de service wil initialiseren. In het voorbeeld wordt aangegeven dat de service volledige toegang heeft tot de gegevens en dat de operaties van de service alles mogen doen met de gegevens. m.a.w. Alle HTTP-methoden zijn toegelaten. In figuur 5.3 kan je zien welke entiteiten er beschikbaar worden gesteld. Listing 5.1: Codevoorbeeld WCF data service 1 2 3 4 5 6 7 8 9
public class DataService : DataService < MonitoringFactsEntities > { public static void In itiali zeServ ice ( D a t a S e r v i c e C o n f i g u r a t i o n config ) { config . S e t E n t i t y S e t A c c e s s R u l e ( " * " , EntitySetRights . All ) ; config . S e t S e r v i c e O p e r a t i o n A c c e s s R u l e ( " * " , S e r v i c e O p e r a t i o n R i g h t s . All ); config . Da t a Se r v ic e B e ha v i or . Max Pr ot oc ol Ve rs io n = D a t a S e r v i c e P r o t o c o l V e r s i o n . V2 ; } }
Hoofdstuk 5. Gebruikte technologie¨en
27
Figuur 5.3: De entiteiten van het data model
5.3
Language Integrated Query (LINQ)
Dit is een technologie die standaard met het .NET framework wordt meegeleverd. Het is een querytaal die rechtstreeks in een C# programma kan gebruikt worden. Het lijkt sterk op SQL, maar het gebruikt een andere volgorde voor de sleutelwoorden ( from, where, select, . . . ) die leesbaarder zijn voor de programmeur. Op wat wordt de query uitgevoerd? Meestal zal dit een collectie-object zijn van het .NET framework, bijvoorbeeld een ArrayList. Het hoeft niet noodzakelijk een collectie-object te zijn. Zolang het object de interface IEnumerable of IQueryable implementeerd zal het mogelijk zijn om een LINQ-query te schrijven met dat object als
Hoofdstuk 5. Gebruikte technologie¨en
28
databron. Zo is het ook mogelijk om LINQ te gebruiken met een web service of ADO Entity Framework of een combinatie van beiden zoals bij OData. Het voordeel van LINQ is dat het onafhankelijk is van de gebruikte databron. Het kan een databank zijn, maar het kan ook een XML-bestand zijn. Bij het uitvoeren van de query zal de LINQ-query worden omgezet naar de corresponderende query taal van de databron. Het volgende voorbeeld geeft de structuur van een LINQ-query aan. Het zal alle monitoring facts ophalen die afkomstig zijn van het bedrijf ICORDA van de machine “WS-DE-STG03” voor de categorie “Hard disk”. Het resultaat zal een collectie van MonitoringFact objecten zijn, gesorteerd op het ID van de monitoring fact. Listing 5.2: voorbeeld LINQ-query 1 2 3 4 5 6
from fact in DataService . Dat aS er vi ce Co nt ex t . MonitoringFacts where fact . Repertor . Benaming1 . Equals ( " ICORDA nv " ) && fact . Product . Equals ( " WS - DE - STG03 " ) && fact . Category . Equals ( " Hard disk " ) orderby fact . MonitoringFactID select fact
De volgende opsomming geeft een aantal manieren waarop LINQ kan gebruikt worden. • LINQ to SQL wordt gebruikt waneer de databron een databank is. De tabellen van de databank worden afgebeeld op klassen en de records die worden opgehaald worden in objecten omgezet. Om de records op te halen wordt de LINQ-query omgezet in een SQL-query. Vervolgens wordt de SQL-query uitgevoerd met een aantal records als resultaat. Door de properties van de objecten te mappen op de velden van de records, kan een object aangemaakt worden en verder gebruikt worden in het programma. • LINQ to XML is een technologie om te werken met XML. Het lijkt op Document Object Model4 (DOM). Het verschil met DOM is dat LINQ to XML eenvoudiger is om mee te werken, en dat het minder is belastend voor het programma. Het laat ook toe om gemakkelijk objecten van het XML-document om te zetten naar objecten van een ander type. • LINQ to DataSet is enkel te gebruiken als je met ADO.NET werkt. In principe heb je geen LINQ nodig om data van een databron te kunnen ophalen met ADO.NET, maar het is wel eenvoudiger. Door met LINQ te werken kan je 4
Document Object Model is een interface om XML in het geheugen op te slaan, delen van de XML op te vragen of de XML aan te passen. Daarna kan het terug naar een bestand worden geschreven.
Hoofdstuk 5. Gebruikte technologie¨en
29
informatie van verschillende tabellen opvragen en ze daarna met LINQ overlopen. Het DataSet object wordt dan de databron van de LINQ-query. • LINQ to Objects wordt gebruikt om objecten te kunnen overlopen en properties ervan op te vragen of volledig nieuwe objecten aan te maken. Het is een beter alternatief dan het schrijven van een foreach lus die verwarrend en complex kan worden door het gebruik van if-else structuren. Door gebruik te maken van LINQ kunnen de if-else structuren vervangen worden door ´e´en where-clausule die veel korter zal uitvallen en overzichtelijker is. • LINQ to Entities is een combinatie van ADO Entity Framework en LINQ. Het ADO Entity Framework is de databron die gebruikt wordt om objecten van de verschillende tabellen van de databank te kunnen opvragen. Het lijkt in zekere zin op LINQ to SQL, maar laat wel toe dat klassen die gebruikt nog kunnen worden aangepast. Dit is niet mogelijk bij LINQ to SQL. • Er zijn nog andere manieren waarop LINQ kan gebruikt worden. Er zijn bijvoorbeeld technologie¨en die toelaten LINQ te gebruiken in combinatie met een web service. Hierbij spreek je de web service aan als databron.
5.4
DevExpress
DevExpress is een bedrijf dat developer tools en libraries voorziet om grafische interfaces te ontwerpen. De developer tools zijn direct integreerbaar in Visual Studio. Code Rush bijvoorbeeld voorziet in handige functies zoals automatisch aanvullen van code of codegeneratie voor klassen. Het kan ook code controleren op syntax en opbouw. Een voorbeeld hiervan is dat het kan aangeven dat een property als constante kan beschouwd worden of dat er geen code onder een if-structuur staat en dus overbodig is. Dit wordt dan vertaald in warnings en errors van de compiler. De bibliotheken die DevExpress voorziet zijn vooral voor het maken van grafische interfaces, zowel voor desktop applicaties als voor web applicaties, maar ook voor mobiele applicaties. Naast de extra controls die DevExpress voorziet, zijn er ook andere bibliotheken voor het communiceren met een databank en het gebruik van LINQ. Deze bibliotheken bieden meer functionaliteit dan de standaard controls voor Windows Forms of ASP.NET applicaties. Een voorbeeld: bijna elke control waar informatie kan ingegeven of kan geselecteerd worden, kan aan een databron gekoppeld worden. Automatisch wordt er dan een binding source object aangemaakt om de data te voorzien
Hoofdstuk 5. Gebruikte technologie¨en
30
voor de control. De gebruikte controls worden verder in deze scriptie besproken. Zowel de controls als de gebruikte patterns die bij de controls horen worden besproken.
5.5
Model View Viewmodel (MVVM)
Dit design pattern wordt veel gebruikt bij het maken van master-detail5 control in een gebruikersapplicatie. Met behulp van de controls die DevExpress voorziet is dit zeer gemakkelijk te implementeren.
5.5.1
Model View Controller (MVC)
Omdat MVVM afgeleid is van MVC, wordt eerst MVC verklaard voor we aan MVVM beginnen. Het bestaat uit drie delen: het model, de view en de controller. Het model zijn de klassen die alle gegevens moeten opslaan. Het model is een voorstelling van de realiteit in het programma. Voor elk object in de “echte” wereld is er een object in het programma. Elke klasse in het model legt vast hoe zo’n object wordt beschreven. De view dient om de gegevens die zijn opgeslagen in het model weer te geven aan de gebruiker. Het maakt het model begrijpbaar voor een gebruiker op een manier waarbij hij de structuur van het model niet hoeft te kennen. De controller is de component die tussen het model en de view zit. Het is de taak van de controller om de functionaliteit van de view te vertalen naar instructies die het model moeten aanpassen. De controller kan ook de view aanpassen op basis van model. Het is mogelijk dat bepaalde acties niet meer zijn toegelaten wanneer er zich een bepaalde situatie voordoet in het model. Om dit alles nog eens samen te vatten: Wanneer een gebruiker een actie onderneemt in de view, zal de controller eerst controleren of er iets in de view moet aangepast worden en daarna zal hij het model aanpassen. Wanneer het model is aangepast, wordt de view hiervan op de hoogte gebracht.
Figuur 5.4: Model View Controller 5
Master-detail control: een combinatie van controls, waarvan een control bepaald welke informatie er wordt getoond in de rest van gebruikersinterface. bv. een tabel waarin je een rij kan selecteren. De geselecteerde rij bepaalt welke informatie in de rest van scherm wordt getoond.
Hoofdstuk 5. Gebruikte technologie¨en
5.5.2
31
Algemeen
Net als bij Model View Controller heb je drie componenten. Je hebt het model dat een zo goed mogelijke representatie is van de realiteit. De view dient om de informatie van het model voor te stellen op een overzichtelijke en begrijpbare manier. De controller, die normaal de functionaliteit van de view regelt met behulp van het model, is vervangen door een viewmodel. Dit is niets anders dan het model op een andere manier voorgesteld, zodat het in de view component kan getoond worden. Het viewmodel en de view zijn dan ook aan elkaar gekoppeld. Door op deze manier te werken kan je zonder het model te moeten aanpassen extra properties voorzien die zijn samengesteld uit properties afkomstig van het model. Een viewmodel object moet dus een instantie van het model object bevatten zodat het alle properties van het model object kan gebruiken. De view zal dan voor elke property van de viewmodel klasse een veld hebben die de waarde van deze property correct voorstelt. Wanneer het toegelaten is om ook wijzigingen aan te brengen, kan de view een event genereren om aan te geven wat er moet veranderen. Het respectievelijke viewmodel object zal dit ontvangen en het model aanpassen.
Figuur 5.5: Schema Model View Viewmodel
Hoofdstuk 5. Gebruikte technologie¨en
32
Wanneer het model ook geregeld zou veranderen, kunnen er extra events vanuit het model nodig zijn. Dan kan het model laten weten aan het viewmodel dat het veranderd is, en het viewmodel kan op zijn beurt de view laten weten dat het zijn inhoud moet aanpassen. Dit kan nodig zijn als een aanpassing door de gebruiker tot meerdere aanpassingen in het model zou kunnen leiden. Op die manier is de meest recente data beschikbaar voor de gebruiker. Het verschil tussen MVC en MVVM zit hem duidelijk in de viewmodel component van het pattern. Het is nu het viewmodel dat wordt aangesproken, wanneer de view zijn informatie wil updaten, maar ook het model laat aan het viewmodel weten dat het is veranderd. Het model en de view zijn dus volledig van elkaar gescheiden. Nog een verschil is dat de controller meestal een enkel object is en het viewmodel is een collectie van objecten die het model moet representeren. Voor elk object in het model moet er ook een object in het viewmodel zijn. De view moet dus weten welk viewmodel object hij moet aanspreken. Hierdoor neemt het geheugengebruik bij MVVM toe ten opzicht van MVC, maar de logica van het viewmodel zal eenvoudiger zijn dan die van de controller.
5.5.3
MVVM met DevExpress
In DevExpress wordt dit ge¨ımplementeerd door gebruik te maken van data binding. De view zal hier dus een component uit de bibliotheek van DevExpress zijn. De view zal at design time kunnen koppelen met een klasse die je zelf voorziet, dit is een viewmodel klasse. Er is echter wel een kleine omweg nodig. Je moet eerst een binding source object aanmaken, en dit object koppelen aan de viewmodel klasse. Daarna moet je de component koppelen aan de binding source. Deze stappen moeten gevolgd worden, omdat een DevExpress component standaard niet kan koppelen met een klasse. Op die manier kan voor elke property in de viewmodel klasse een component in de view voorzien worden. De property wordt dan aan de component gekoppeld met zijn naam. Om het af te werken moet je in de code enkel nog zeggen waar de binding source zijn informatie moet halen. Deze informatie moet een collectie van viewmodel objecten zijn. Om aanpassingen aan het model toe te laten, is het genoeg om een setter te voorzien voor de respectievelijke property in de viewmodel klasse. Het moet natuurlijk ook mogelijk zijn in de view om een property te kunnen aanpassen. Net als in figuur 5.5 zal er een event gegenereerd worden om aan te geven welke aanpassing er aan het model moet aangebracht worden. Het voorgaande kon allemaal at design time gebeuren, maar de conversie van de model objecten naar viewmodel objecten gebeurt at runtime. Voor de binding source zijn
Hoofdstuk 5. Gebruikte technologie¨en
33
collectie van viewmodel objecten krijgt toegewezen, moet de collectie eerst worden aangemaakt. Voor elk object in het model wordt een viewmodel object aangemaakt door de constructor van de viewmodel klasse op te roepen met als enige argument het model object. Als de volledige conversie is afgelopen, kan een viewmodel object via de binding source doorgegeven worden aan de view voor het tonen van de data. In het volgende voorbeeld wordt er een voorbeeldimplementatie van dit design pattern voorgesteld. De eerste klasse in het voorbeeld is het viewmodel van het MVVM-pattern. Het verwacht een modelklasse die je op een of andere manier meegeeft aan de constructor. In de view maak je gebruik van een BindingSource object, dat je toekent aan de DataSource property van een control. Het BindingSource object heeft zelf ook een DataSource property, dat een ICollection object verwacht. Een goede keuze hiervoor is een BindingList object, omdat de methoden van de BindingList klasse ervoor zorgen dat events worden opgeroepen bij de BindingSource klasse. Aan de DataSource property van het BindingSource object ken je dan het BindingList object toe. Nu kan de grid control een aantal kolommen hebben die overeenkomen met de properties van de viewmodel klasse, en het is niet beperkt tot de properties van de model klasse. De ConvertMonitoringFactsToViewModels methode zorgt voor de conversie van model objecten naar viewmodel objecten. De DataService klasse zorgt voor de connectie met de databank. Listing 5.3: Codevoorbeeld: gebruik Model View Viewmodel 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
// Viewmodel klasse public class MonitoringFactVM { private MonitoringFact Model { get ; set ; } public MonitoringFactVM ( MonitoringFact model ) { Model = model ; } public int FactID { get { return Model . MonitoringFactID ; } } public string Subject { get { return string . Format ( " KlantID : {0} , Product :{1} , Categorie : {2} " , Model . RepertorID , Model . Product , Model . Category ) ;
Hoofdstuk 5. Gebruikte technologie¨en 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
} } public string Remark { get { return Model . Remark ; } set { Model . Remark = value ; } } } // Klasse voor de View public partial class GridForm : Form { private GridControl gridControl ; private BindingSource m o n i t o r i n g F a c t G r i d B i n d i n g S o u r c e ; public GridForm () { I n i t i a l i z e C o m p o n e n t s () ; m o n i t o r i n g F a c t G r i d B i n d i n g S o u r c e = new BindingSource () ; m o n i t o r i n g F a c t G r i d B i n d i n g S o u r c e . DataSource = C o n v e r t M o n i t o r i n g F a c t s T o V i e w M o d e l s ( DataService . MonitoringFact ) ; }
45 46 47 48 49 50 51 52
53 54 55 56 57 58 59 60
private void FormLoad () { gridControl = new GridControl () ; gridControl . DataSource = m o n i t o r i n g F a c t G r i d B i n d i n g S o u r c e ; } private BindingList < MonitoringFactVM > C o n v e r t M o n i t o r i n g F a c t s T o V i e w M o d e l s ( IEnumerable < MonitoringFact > facts ) { BindingList < MonitoringFactVM > VMList ; foreach ( var fact in facts ) { VMList . Add ( new MonitoringFactVM ( fact ) ) ; } return VMList ; } }
34
Hoofdstuk 5. Gebruikte technologie¨en
35
Het voorbeeld hiervoor kan nog verder verbeterd worden. In het voorbeeld wordt de databank vanuit de view aangesproken. Dat zou ervoor zorgen dat de databank elke keer zou worden aangesproken als er informatie nodig is in de view. Om dit te omzeilen gaan we ervoor zorgen dat de data een keer volledig wordt opgehaald en daarna lokaal gefilterd wordt. Hiervoor kunnen we een statische klasse gebruiken die een private statisch lidveld heeft dat de informatie lokaal zal bijhouden. Dan wordt ook een publieke property gemaakt die enkel toelaat de informatie op te vragen. De property zal dan moeten controleren of de informatie al is opgevraagd. Als dit niet het geval is, dan moet de databank gecontacteerd worden om alle informatie op te halen. Het voorbeeld ziet er dan als volgt uit: Listing 5.4: Codevoorbeeld: verbeterde connectie met databank 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
public static class G r i d C o n t r o l D a t a S o u r c e H e l p e r { private static BindingList < MonitoringFactVM > gridModels public static BindingList < MonitoringFactVM > GridModels { get { if ( gridModels == null ) gridModels = Ge ne ra te Gr id Mo de ls () ; return gridModels ; } } private static BindingList < MonitoringFactVM > Ge ne ra te Gri dM od el s () { var models = new BindingList < MonitoringFactVM >() ; foreach ( var fact in DataService . MonitoringFact ) models . Add ( new MonitoringFactVM ( fact ) ) ; return models ; } } public partial class GridForm : Form { // ... public GridForm () { I n i t i a l i z e C o m p o n e n t s () ; m o n i t o r i n g F a c t G r i d B i n d i n g S o u r c e = new BindingSource () ; m o n i t o r i n g F a c t G r i d B i n d i n g S o u r c e . DataSource = G r i d C o n t r o l D a t a S o u r c e H e l p e r . GridModels ; } // ... }
Hoofdstuk 5. Gebruikte technologie¨en
36
Door gebruik te maken van de GridControlDataSourceHelper wordt er een keer met de databank gecommuniceerd. Wanneer dezelfde data nog eens nodig is moet deze niet meer opgehaald worden en bijgevolg zal het programma sneller reageren. Dit maakt het ook eenvoudiger om gebruik te maken van multithreading. Nu moet er enkel voor gezorgd worden dat de GridModels property thread safe 6 is. Om ervoor te zorgen dat de databank niet meerdere keren tegelijk wordt aangesproken wordt de toegang tot het gridModels lidveld afgesloten als een andere thread het lidveld gebruikt. In C# doe je dit met het lock sleutelwoord. Listing 5.5: Codevoorbeeld: threadsafe code 1 2 3 4 5 6 7 8 9 10 11 12 13
private static object gridModelLock = new object () ; private static BindingList < MonitoringFactVM > gridModels public static BindingList < MonitoringFactVM > GridModels { get { lock ( gridModelLock ) { if ( gridModels == null ) gridModels = Ge ne ra te Gr id Mo de ls () ; return gridModels ; } } }
5.6
Windows Services
Een Windows service is het equivalent van daemons in een UNIX besturingssysteem. Het is gemaakt om in de achtergrond te werken en heeft geen interactie van een gebruiker nodig. Meestal wordt een Windows service gestart bij het opstarten van het besturingssysteem, maar het is natuurlijk ook mogelijk om de service manueel te starten en te stoppen.
5.6.1
Een Windows service maken
Een Windows service kan gemakkelijk vanuit Visual Studio aangemaakt worden. Het projecttype dat je moet kiezen is Windows Service en je krijgt een standaard configuratie voor de nieuwe service. 6
Een programma is thread safe als dezelfde variabele niet door verschillende threads tegelijk kan gebruikt worden. In het voorbeeld is dit het gridModels lidveld van de GridModelsDataSourceHelper.
Hoofdstuk 5. Gebruikte technologie¨en
37
De code die voor jou is gegenereerd bestaat uit een klasse die is afgeleid van het type ServiceBase. Deze basisklasse voorziet een aantal methoden die toelaten de service te starten, te stoppen, te pauzeren en terug te laten verder gaan. Ook worden er methoden voorzien om te specificeren wat er moet gebeuren op die momenten. De service heeft ook een aantal handige properties die aangeven of een service kan gestopt of gepauzeerd worden. Zoals elke applicatie in .NET is er een main methode die de service aanmaakt door de constructor van de service op te roepen en de service te starten door de Start methode te gebruiken.
5.6.2
Installeren van een Windows service
Om een service gemakkelijk te kunnen installeren, moet een installer aan het project worden toegevoegd. Wanneer je dit doet, krijg je een ServiceInstaller en een ServiceProcessInstaller. Bij de ServiceInstaller kan je de naam van de service vastleggen en beslissen of de service automatisch moet opstarten. Bij de ServiceProcessInstaller kan je instellen met welke gebruiker de service zal opstarten. Meestal zal de gebruiker ingesteld worden op LocalSystem, die overal rechten heeft op het systeem, wat kan leiden tot een onveilige service. Daarom wordt de gebruiker LocalService gebruikt. Deze gebruiker heeft minder rechten op de lokale machine, en geeft enkel anonieme credentials als het moet connecteren met een remote server. Deze tweede optie is dus aan te raden wanneer het veilig moet zijn. Om de service te installeren kan je gebruikmaken van installutil.exe. Het enige wat je moet doen is de uitvoerbare versie van het Visual Studio project vinden en dat meegeven als argument in de opdrachtprompt. Met dezelfde utility kan je de service terug de¨ınstalleren, door de /u optie mee te geven. Nu kan je de service starten, stoppen en pauzeren vanuit de Services.msc utility van het Windows besturingssysteem. Hier kan je ook argumenten opgeven die kunnen gebruikt worden door de service. Je kan ook gebruikmaken van het net commando of het sc commando, gevolgd door ’start‘, ’stop‘, ’pause‘ of ’continue‘ en dan de naam van de service die je wil starten, stoppen, pauzeren of laten verder werken nadat het gepauzeerd werd.
Hoofdstuk 5. Gebruikte technologie¨en
5.7
38
Team Foundation Server
Dit is een hulpmiddel om versies van het programma te kunnen beheren. Het houdt een lijst bij van bestanden die zijn aangepast sinds de laatste keer dat er een nieuwe versie op de server werd gezet. Het is dan mogelijk om terug te keren naar de vorige versies van de code. Op deze manier kan iedereen die met de TFS is geconnecteerd jouw code bekijken en zelf de code aanpassen. Die persoon moet dan zijn nieuwe versie terug op de TFS zetten zodat iedereen kan vertrekken van de nieuwe versie. Door met TFS te werken is er automatisch een back-up van de code die je hebt geschreven. Als de computer waar dat project is aangemaakt zou crashen, kan er nog altijd van de laatste nieuwe versie verder gewerkt worden. De aanpassingen die niet op de server staan zijn dan wel verloren, maar het is wel beter dan helemaal opnieuw te moeten beginnen.
Hoofdstuk 6 Componenten van de Remote Controlled Alert & Task Agent 6.1
De verschillende componenten
De Remote Controlled Alert & Task Agent (RCATA) module bestaat uit drie delen: • Een data service zorgt voor de connectie met de databank. Deze kan zowel gegevens ophalen als gegevens wegschrijven naar de databank. • Een Windows service die zorgt voor het ophalen van de meest recente records uit de monitoring facts tabel van de databank, en het uitvoeren van de taak wanneer er een record voldoet aan de gespecificeerde alert filter. • Het grootste deel van de agent is de gebruikersapplicatie. Deze kan gebruikt worden voor het bekijken van de gegenereerde alerts, alsook voor het aanpassen van de configuratie voor het genereren van alerts.
6.2
De Data Service
De data service is de component die de verbinding met de databank zal verzorgen. Het maakt gebruik van het OData protocol, wat in dit geval een combinatie is van ADO Entity Framework en Windows Communication Foundation data service (WCF) (zie hoofdstuk 5). De enige taak van deze component is communiceren met de databank. Dit houdt in dat het alle objecten uit de databank kan ophalen door gebruik te maken van LINQ to Entities en het ADO Entity Framework. Daarnaast moet het ook toelaten objecten aan te passen, toe te voegen of te verwijderen in de databank. WCF wordt gebruikt om de aanvragen door te sturen naar de server en het ADO Entity Framework wordt gebruikt om de gegevens op te halen of aan te passen. Deze data service is in twee gesplitst. Enerzijds heb je het deel dat dient voor het ophalen van de monitoring facts, repertors en alerts en anderzijds heb je het deel dat 39
Hoofdstuk 6. Componenten van de Remote Controlled Alert & Task Agent
40
dient voor het ophalen en aanpassen van de configuratie. Ze zijn ook verschillend ge¨ımplementeerd. Het model werd eerst in code opgebouwd, dus moest het deel voor de configuratie met ADO Entity Framework Code First ge¨ımplementeerd worden. Het andere deel is met ADO Entity Framework Database First ge¨ımplementeerd, omdat de databank alreeds bestond. De tabellen werden in klassen omgezet met een entity data model.
6.3
De Windows Service
De Windows service is de component die het algoritme, dat werd beschreven in hoofdstuk 4, periodiek zal uitvoeren. Hiervoor maakt het gebruik van de data service om alle benodigde gegevens op te halen. Ook wanneer de gegenereerde alerts moeten worden opgeslagen, zal de data service gebruikt worden. Wanneer de service veel gegevens moet binnenhalen, moet hij deze ook allemaal verwerken. De tijd die nodig is om alle informatie te verwerken kan dan langer zijn dan het interval dat wordt gebruikt om de volgende informatie op te halen. Hierdoor zou overlapping van verschillende controles op de opgehaalde informatie kunnen ontstaan. Om deze mogelijke overlapping te voorkomen wordt er bijgehouden of de service bezig is met het verwerken van informatie. Wanneer dit het geval is zal het ophalen van de volgende informatie uitgesteld worden totdat de verwerking van de huidige informatie volledig afgerond is. Het tijdstip van wanneer de nieuwe monitoring facts in de vorige ronde zijn opgehaald, wordt in de volgende ronde gebruikt om de nieuwe monitoring facts op te halen. Op die manier zullen alle monitoring fact worden gecontroleerd. Zoals reeds eerder vermeld worden de alerts opgeslagen. Dit is niet alleen om unieke alerts te kunnen identificeren, maar ook om het mogelijk te maken dat de service kan herstart worden. Zonder bijkomende opslag van gegenereerde alerts zou de service niet meer weten welke alerts al gemeld zijn en welke nog niet. Bij het (her)starten van de service zal deze de opgeslagen alerts terug ophalen en verder werken alsof hij niet gestopt is.
6.4
De Gebruikersapplicatie
De gebruikersapplicatie bestaat uit twee delen. Enerzijds is er de Alert Viewer en anderzijds is er de configuratie-editor.
Hoofdstuk 6. Componenten van de Remote Controlled Alert & Task Agent
6.4.1
41
Alert Viewer
Het doel van de Alert Viewer is om snel alerts te kunnen opzoeken op klantnaam, machinenaam en de categorie van de alert. Een voorbeeld: Klant X heeft voor machine Y een alert die zegt dat de schijfruimte minder dan 5% van de totale capaciteit bedraagt. Alert opzoeken: Om snel te kunnen opzoeken, wordt er gebruikgemaakt van drie hoofdcomponenten. Je hebt een tree list die dient voor het opzoeken van de klanten en de machines met zijn onderverdelingen. De selectie in de tree list wordt gebruikt om de grid view op te vullen. In de detail layout view krijg je een volledig overzicht van wat geselecteerd is in de grid view. Deze zal voor elk kenmerk van de alert een veld tonen met zijn respectievelijke waarde.
Figuur 6.1: Treelist
Figuur 6.2: DataLayoutControl
Figuur 6.3: GridControl
Hoe werken deze drie componenten samen? De tree list heeft drie onderverdelingen. Het is mogelijk om enkel de gelezen, enkel de ongelezen of alle alerts te bekijken. Onder de tak met alle alerts vind je de klanten van ICORDA. Onder een klant vind je de
Hoofdstuk 6. Componenten van de Remote Controlled Alert & Task Agent
42
machines van die klant. Onder elke machine vind je de categorie¨en waarop er onderverdeeld wordt voor alerts (bv hard disk, anti malware, back-up, . . . ). De tak met de gelezen en ongelezen alerts hebben geen onderverdelingen. In de grid view zal je dan alle klanten vinden die respectievelijk gelezen of ongelezen alerts hebben. Bij het aanklikken van een alert in de grid view zal je een detailvoorstelling van de alert krijgen in de detail layout view. Deze geeft meer informatie over de alert, zoals het onderwerp van de e-mail die erbij hoort alsook de body van die e-mail. Er wordt ook meer informatie gegeven over wie de klant is en wat de alert precies inhoudt. Gelezen en ongelezen alerts: Het onderscheid tussen een gelezen alert en een ongelezen alert wordt aangeduid door de tekst van de alert in de grid view in het vet te zetten (zoals bij een e-mail programma). Wanneer de ongelezen alert wordt geselecteerd zal de vette tekst overgaan in normale tekst. Op dit moment is de alert als gelezen gemarkeerd. In de tree list kan je zien hoeveel ongelezen alerts er nog zijn voor de bijhorende onderverdeling. Wanneer een alert als gelezen gemarkeerd wordt, zal dit ook te merken zijn in de tree list. De aantallen naast de klantnaam, de machine of de categorie zullen verlagen doordat er een gelezen alert minder is. Ook het verschil tussen gewone alerts en critical alerts is te zien door het icoontje in de eerste kolom. De gele driehoek staat voor een gewone alert, het rode icoon staat voor de critical alerts. Extra functies: Er zijn nog twee kleine functies die de alert viewer aanbiedt. De eerste is dat je ook alerts terug kan verwijderen. Als de alert is gelezen en onder de ”Read“ tak komt te staan, dan kan je de alert verwijderen. Het is dus verplicht om de alert minstens een keer te bekijken. De tweede functionaliteit is deze om een alert toe te kennen aan iemand. Een alert kan een vrij groot probleem aan het licht brengen en dan moet dit probleem opgelost worden. Door de alert toe te kennen aan een persoon kan het probleem opgelost worden. De persoon in kwestie zal ook een e-mail ontvangen om te laten weten dat de taak om het probleem op te lossen aan hem/haar is toegewezen. Wanneer het probleem opgelost is, kan dit aangeduid worden in de applicatie zodat iedereen dit kan zien. Het verschil tussen een toegewezen alert en een niet toegewezen alert is te zien in figuur 6.4 en figuur 6.5.
Figuur 6.4: Niet toegewezen alert
Figuur 6.5: Toegewezen alert
Deze applicatie zorgt er dus voor dat een gebruiker snel een alert kan opzoeken. Ofwel
Hoofdstuk 6. Componenten van de Remote Controlled Alert & Task Agent
43
zoekt de gebruiker bij de gelezen of ongelezen alerts, of hij gaat naar de klantennaam, de machinenaam en de categorie van de machine zoeken om de lijst van alerts te filteren. Daarnaast is het ook mogelijk om de alerts te verwijderen. Indien nodig kan een alert ook toegewezen worden aan iemand om het probleem, dat eraan verbonden is, op te lossen.
6.4.2
De Configuratie-editor
Het tweede deel van de gebruikersapplicatie dient voor het aanpassen van de configuratie voor het genereren van alerts. Je kan hier alle alert filters bekijken en aanpassen. Het is ook mogelijk om alert filters toe te voegen of te verwijderen. De alert filters kunnen op dezelfde manier bekeken worden als de alerts in de Alert Viewer. Helemaal links heb je een lijst met de namen van de klanten en het aantal alert filters ernaast. Rechts daarvan kan je alle alert filters van de klant bekijken. Een alert filter selecteren zorgt ervoor dat je de ingestelde configuratie kan bekijken en aanpassen.
Figuur 6.6: Klanten met alert filter teller
6.4.2.1
Figuur 6.7: Alert filters
Configuratie van een alert filter
Met de configuratie-editor kan je vastleggen welke alerts zullen gegenereerd worden. Dit doe je door een alert filter aan te maken voor de alert die je wil laten genereren. In de alert filter komen de voorwaarden die moeten voldaan zijn om een alert te laten aanmaken. In de alert filter komt ook de configuratie voor de e-mail die wordt verstuurd als er een alert wordt gegenereerd.
Hoofdstuk 6. Componenten van de Remote Controlled Alert & Task Agent
44
De voorwaarden: Een alert filter heeft algemene voorwaarden die moeten voldaan zijn om een alert te kunnen genereren. Deze voorwaarden worden ingesteld met behulp van de filter control van DevExpress (zie hoofdstuk 7). In de filter control kan je enkel eigenschappen van de monitoring fact gebruiken om de voorwaarden vast te leggen. Een voorbeeld: Category == ’Hard disk’ AND Description == ’Used space’ AND Value >= 90.00. Alle bruikbare properties van een monitoring fact zijn te vinden in figuur 5.3.
Figuur 6.8: FilterControl
Alert Filter Extensie: Wanneer de voorwaarden niet genoeg zijn om goede alerts te genereren, is er de optie om een alert filter extensie te gebruiken. Er zijn drie opties waaruit je kan kiezen. Deze drie opties komen overeen met de drie AlertFilterExtension klassen van het model. De DateTimeFilterExtension en de EqualForDaysFilterExtension worden geconfigureerd door het aantal dagen in te geven. In het eerste geval zal er naar een datum worden gezocht die een aantal dagen vroeger is dan vandaag. Bij de tweede alert filter extensie zal er gecontroleerd worden of de Value property van de monitoring fact al het ingestelde aantal dagen ongewijzigd is gebleven. Bij de NumberRegexFilterExtension kan er gekozen worden tussen twee opties. De eerste optie gaat een tijdsaanduiding (bv. 1h 5m) uit de value property halen en omzetten naar minuten. De tweede gaat een getal uit de value property halen (bv. 5x failed). Bij beide moet je ingeven met welke waarde er moet vergeleken worden en welke operator (=, <, >, <=, >=) je daarvoor gebruikt.
Hoofdstuk 6. Componenten van de Remote Controlled Alert & Task Agent
Figuur 6.9: Control voor DateTimeFilterExtension en EqualForDaysFilterExtension
45
Figuur 6.10: Control voor NumberRegexFilterExtension
E-mail configuratie: Voor de e-mail te configureren moet je kiezen uit een aantal ontvangers voor de e-mail. Dit kunnen er meerdere zijn, maar er moet wel minstens een ontvanger zijn. Als je de ontvangers hebt gekozen kan je bepalen wat er in het onderwerp komt en wat er in de body van de e-mail komt. Beide worden met behulp van checkboxes geconfigureerd. Je krijgt ook onmiddelijk een voorbeeld te zien van het onderwerp en de body van de e-mail. Dan heb je nog een laatste optie om er een mogelijke oplossing bij te zetten. Deze komt dan mee in de e-mail.
Figuur 6.11: Stap 1: De ontvanger kiezen
Figuur 6.12: Stap 2: Het onderwerp van de e-mail instellen
Hoofdstuk 6. Componenten van de Remote Controlled Alert & Task Agent
46
Figuur 6.13: Stap 3: De inhoud van de e-mail instellen
Extra: Naast de drie stappen die moeten worden doorlopen, zijn er ook nog een aantal extra’s die de configuratie kunnen be¨ınvloeden. Zo kan de naam van de alert filter nog aangepast worden na het aanmaken van de alert filter. Ook kan er aangeduid worden of de alert filter een critical alert moet genereren of niet. Dit zijn twee dingen die in de grid view kunnen aangepast worden. 6.4.2.2
Functies van de configuratie-editor
Om het de gebruiker gemakkelijker te maken zijn er een aantal functies aan de applicatie toegevoegd. Aanmaken van alert filters: Bij het aanmaken van een alert filter kan de gebruiker uit een lijst van klanten kiezen door ze te selecteren. Voor elk van de geselecteerde klanten zal dan een alert filter aangemaakt worden. Zo moet de gebruiker niet elke keer opnieuw dezelfde handeling uitvoeren om een aantal alert filters aan te maken die dezelfde naam en configuratie hebben.
Hoofdstuk 6. Componenten van de Remote Controlled Alert & Task Agent
47
Figuur 6.14: Nieuwe alert filter aanmaken
Template alert filters: Een eerste bijkomende functie van de configuratie-editor is het gebruik van template alert filters. Dit zijn alert filters die niet zullen gebruikt worden om alerts te genereren, maar wel om andere alert filters aan te maken. Een gebruiker kan een template alert filter aanmaken door van een gewone alert filter een template alert filter te maken, of door een volledig nieuwe template alert filter aan te maken. Deze template alert filters zijn vooral handig wanneer een alert filter veel opnieuw moet ingesteld worden. Dan kan een gebruiker kiezen uit de templates om een nieuwe alert filter te maken. Zo heeft de gebruiker meteen een alert filter die kan gebruikt worden en waar geen extra configuratiewerk voor nodig is. Een gebruiker kan zo een template alert filter aanmaken die controleert of de schijfruimte van een machine minder is dan 10%. Vervolgens kan hij voor elke klant een alert filter laten aanmaken die controleert of de machines van de klant nog meer dan 10% schijfruimte over hebben. Een template kan na zijn aanmaak terug worden verwijderd of worden aangepast. Het aanpassen of verwijderen van een template alert filter heeft geen effect op de alert filters die met die template zijn aangemaakt.
Hoofdstuk 6. Componenten van de Remote Controlled Alert & Task Agent
48
Figuur 6.15: Templates beheren
Alert filters verwijderen: Alert filters kunnen ook verwijderd worden. Dit kan op twee manieren. Ofwel doet de gebruiker dit per klant. Het enige wat hij dan moet doen is de alert filters aanduiden die moeten worden verwijderd en ze verwijderen. Bij de tweede manier krijgt de gebruiker een lijst van alle alert filters. Deze lijst kan gefilterd worden door op een van de kolommen te klikken en de optie te kiezen waarop moet gefilterd worden. Daarna kan de gebruiker alle alert filters aanduiden die moeten worden verwijderd en ze uiteindelijk verwijderen.
Figuur 6.16: Alert filters verwijderen
Hoofdstuk 6. Componenten van de Remote Controlled Alert & Task Agent 6.4.2.3
49
User alert filter configuration
Het is ook mogelijk dat elke gebruiker de algemene configuratie personaliseert. Dit wil zeggen dat een gebruiker de configuratie enkel voor zichzelf kan aanpassen zonder dat er iets aan de algemene configuratie verandert. Dit gebeurt in een aparte applicatie die een beperkte functionaliteit heeft ten opzichte van de configuratie-editor voor de algemene configuratie. In deze applicatie wordt er gecontroleerd welke gebruiker is ingelogd. Als de gebruiker een alert filter wil aanpassen dan zal dat alleen enkel voor hem gebeuren. Er wordt dus een nieuwe alert filter aangemaakt nl. een user alert filter. Dit wil zeggen dat de algemene alert filter volledig wordt gekopi¨eerd en dus begint met dezelfde configuratie als de algemene alert filter. Nu wordt enkel nog de user alert filter aangepast en niet de algemene alert filter. De gebruiker kan ook instellen dat hij niet wenst gebruik te maken van een alert filter. Hij zal dan geen notificaties ontvangen als voor de algemene alert filter een alert wordt gegenereerd. Het enige wat de gebruiker niet kan aanpassen is de configuratie voor de e-mail die wordt verstuurd. Hij kan enkel aangeven dat hij de e-mail niet wil ontvangen.
Figuur 6.17: User alert filters
6.4.2.4
Opslag
Beide configuratie-editors bewaren elke aanpassing in de databank. Hiervoor wordt gebruikgemaakt van het ADO Entity Framework. Dezelfde configuratie kan dan vanuit de Windows service meteen gebruikt worden. Op die manier treedt de configuratie meteen in werking.
Hoofdstuk 6. Componenten van de Remote Controlled Alert & Task Agent
6.5
50
Statement of work
Het statement of work geeft aan hoe de applicatie tot het eindresultaat is gekomen. In deze situatie was dat een opvolging van uitbreidingen op wat al bestond. In de volgende opsomming zal dus telkens een uitbreiding op wat al bestond beschreven worden.
1. De eerste stap was het maken van een consoleapplicatie die kon communiceren met de databank. De functionaliteit van deze consoleapplicatie was niet meer dan de recentste alert filters ophalen, controleren of de categorie ‘Hard disk’ was, de description ‘Used space’ was en dan controleren of de value meer dan 90% was. Als dat lukte moest er ook een e-mail worden verstuurd die de gegevens van de monitoring fact bevatte. Er moest ook voor gezorgd worden dat een alert maar een keer werd gegenereerd. Daarvoor werden de gegenereerde alerts opgeslagen in een XML-bestand. 2. De volgende stap was dat de consoleapplicatie moest kunnen gebruikmaken van een configuratie. Deze configuratie moest natuurlijk kunnen aangepast worden, dus moest er een gebruikersapplicatie bijkomen die deze configuratie kon aanpassen. De configuratie bestond uit een alert filter met enkel een filter string. Deze filter string werd dan omgezet om een query te kunnen uitvoeren op de opgehaalde monitoring facts. De configuratie wordt voor de eenvoud in een XML-bestand opgeslagen. 3. Nu dat er een configuratie is en een consoleapplicatie die op basis van deze configuratie alerts kan genereren is het tijd om de consoleapplicatie te testen in een re¨ele situatie. Daarom werd er een Windows service aangemaakt en ge¨ınstalleerd op een server van ICORDA. Hieruit zijn nog wat fouten naar boven gekomen en vervolgens opgelost. 4. Nu er een Windows service continu alerts kan genereren is het ook de bedoeling dat deze alerts kunnen bekeken worden. Dit was al mogelijk door naar de e-mails te kijken, maar als er veel alerts zijn, is dit geen handig systeem. Daarom werd er nieuwe applicatie aangemaakt die alle alerts op een overzichtelijke manier kan voorstellen. Deze applicatie is de Alert Viewer geworden. 5. Op dit moment werden er alleen maar alerts aangemaakt over capaciteitsproblemen van harde schijf. Het is natuurlijk de bedoeling dat er ook andere alerts kunnen aangemaakt worden. Daarom werden voorstellen gedaan door de ICORDA-medewerkers. Op basis van deze voorstellen werd de configuratie
Hoofdstuk 6. Componenten van de Remote Controlled Alert & Task Agent
51
uitgebreid zodat ook de nieuwe alerts konden aangemaakt worden. In deze stap zijn de alert filter extension klassen toegevoegd aan het model. 6. Omdat de alert filter extensies nog niet konden geconfigureerd worden in de configuratie-editor moest dit eerst mogelijk zijn voordat er aan een volgende stap werd begonnen. De configuratie-editor was op dat moment ook nog niet met de geavanceerdere componenten van DevExpress gemaakt, dus werd de configuratie-editor volledig opnieuw gemaakt met DevExpress-componenten. 7. Nu de algemene configuratie zonder problemen kon worden aangepast, was het tijd om ook een configuratie per gebruiker te introduceren. Hiervoor werd de basis van de algemene configuratie-editor gebruikt waarbij er een aantal elementen werden weggelaten. Hier moest het vooral mogelijk zijn dat alert filters konden aangepast worden door bepaalde gebruikers zonder dat de algemene alert filter werd aangepast. 8. In deze laatste grote stap werd de configuratie naar de databank overgebracht. Dit was tot nu toe nog niet het geval. Hierbij werden de klassen op tabellen gemapt door gebruik te maken van ADO Entity Framework Code First. Hierdoor moesten de configuratie-editors nog eens volledig getest worden om de werking ervan te verzekeren. 9. Een van de laatste uitbreidingen aan het systeem was dat er een onderscheid gemaakt werd tussen critical alerts en gewone alerts. Er werd ook nog een klassenstructuur opgezet zodat het later gemakkelijker zou zijn om nieuwe taken toe te voegen. De enige taak tot nu toe is het versturen van de e-mail. Maar er kan nu eenvoudiger een nieuwe taak bijkomen. 10. De laatste uitbreiding heeft het mogelijk gemaakt om een alert toe te kennen aan een persoon. Hiervoor werd de Alert Viewer uitgebreid aangezien daar alle alerts kunnen bekeken worden. Ook het klassenmodel en het databankmodel werd hiervoor aangepast. Bij de toekenning van een alert aan een persoon wordt ook een e-mail gestuurd om die persoon daarvan op de hoogte te brengen.
Hoofdstuk 7 Componenten van de gebruikersapplicaties Dit hoofdstuk zal de gebruikte componenten toelichten. Voor elke component zal uitgelegd worden wat zijn functionaliteit is en hoe hij gebruikt moet worden.
7.1
De Alert Viewer
Deze applicatie maakt uitsluitend gebruik van DevExpress componenten. Deze DevExpress componenten zijn de GridControl (zie figuur 6.3), de TreeList (zie figuur 6.1) en de DataLayoutControl (zie figuur 6.2). De GridControl is vergelijkbaar met de GridView component van Windows Forms. Het is gemaakt om een collectie van data-objecten te kunnen tonen in tabelvorm. De TreeList is vergelijkbaar met de TreeControl van Windows Forms die je toelaat een hi¨erarchische structuur op te bouwen en te tonen aan de gebruiker (bv. de sidebar van de explorer van het Windows bestandsysteem). De DataLayoutControl dient om een data-object overzichtelijk te kunnen voorstellen aan een gebruiker. Je hebt hier de keuze uit een aantal controls die je zelf kan toevoegen en plaatsen. Elke control in een DataLayoutControl is gebonden aan een property of aan een samenstelling van properties van een data-object. Om deze drie controls van gegevens te voorzien, wordt er gebruikgemaakt van het Model View Viewmodel pattern. Zoals reeds eerder vermeld moet je hiervoor een binding source object aanmaken en de databron daar aan toekennen. De binding source wordt dan als databron gebruikt voor een component. De component is dus de view, in dit geval de GridControl, de TreeList en de DataLayoutControl. Het viewmodel is een zelf aangemaakte klasse, en de objecten van deze klasse komen in een collectie-object dat dan wordt toegekend aan de DataSource property van de binding source. De gegevens zijn afkomstig uit de databank en worden met het ADO Entity Framework opgehaald. De GridControl en de DataLayoutControl maken van dezelfde binding source gebruik en dus ook van dezelfde databron. Dit is eenvoudiger dan twee aparte binding sources, omdat bij het aanduiden van een rij in de GridControl de inhoud van de DataLayoutControl meteen wordt aangepast zonder dat daar extra code voor moet 52
Hoofdstuk 7. Componenten van de gebruikersapplicaties
53
worden geschreven. Bij de DataLayoutControl kan je van verschillende controls gebruikmaken om de properties van objecten te kunnen tonen aan de gebruiker. De controls die je kan gebruiken binnen een DataLayoutControl zijn controls die kunnen worden gekoppeld aan een specifieke property van een object. Hiervoor moet je de naam van de property opgeven bij de control. Vervolgens zorgt de DataLayoutControl ervoor dat de juiste property van een data-object wordt aangesproken om de control een inhoud te geven. Voor een property van het type int wordt standaard de SpinEdit control gebruikt die enkel getallen toelaat. Voor een property van het type string wordt er een MemoEdit gebruikt om goed met tekst te kunnen werken. Voor de TreeList is wel een aparte klasse aangemaakt voor het viewmodel. Om de TreeList te kunnen gebruiken moet er een hi¨erarchie aanwezig zijn in de databron ervan. Deze hi¨erarchie wordt aangemaakt door aan elk element een ID en een parentID toe te kennen. Als de parentID naar een ander element in de databron verwijst zal het niet op het eerste niveau van de TreeList te zien zijn, maar in een lager niveau. Doordat het viewmodel voor de GridControl verschilt van het viewmodel voor de TreeList, en de data in de GridControl moet wijzigen op basis van de selectie in de TreeList, moet er een mechanisme voorzien worden dat snel en effici¨ent kan bepalen welke gegevens moeten worden getoond in de GridControl. De hi¨erarchie van de TreeList is opgebouwd in vier niveaus. Het eerste niveau duidt aan of je de gelezen alerts, de ongelezen alerts of alle alerts wil. Het tweede niveau geeft een lijst van klanten. Het voorlaatste niveau geeft een lijst van alle machines die de klant heeft, en het laatste niveau geeft alle categorie¨en waarvoor er alerts kunnen gegenereerd worden. Het mechanisme om de juiste data op te halen maakt gebruik van deze hi¨erarchie door het te beschouwen als een zoekboom. Om dan snel de gegevens die in de GridControl moeten komen te bepalen, volgen we de parentID’s totdat we bij de top van de boom zijn. We starten telkens bij de geselecteerde knoop van de TreeList. In die knoop vinden we de informatie over de klant, de machine en de categorie van de machine. Dan zoeken we de knoop aan de top, dit is ofwel de Read -knoop, de Unread -knoop of de All -knoop. Op basis hiervan weten we welke alerts moeten worden opgehaald en of de alerts gelezen, ongelezen of beide moeten zijn. Deze informatie wordt dan omgezet naar een where clausule voor een LINQ-query, en deze query wordt dan op zijn beurt gebruikt om de juiste data op te halen voor de GridControl. In figuur 7.1 bv. alle ongelezen alerts te zien.
Hoofdstuk 7. Componenten van de gebruikersapplicaties
54
Figuur 7.1: Alle ongelezen alerts
7.2
De Configuratie-editor
De configuratie-editor maakt ook uitsluitend gebruik van de DevExpress controls. Zoals uitgelegd in hoofdstuk 6 kan de gebruiker alle alert filters per klant bekijken. Een alert filter kan dan geselecteerd worden zodat alle informatie die de alert filter bevat, wordt getoond. Om de klant te kunnen selecteren wordt er gebruikgemaakt van een ListBoxControl in combinatie met het MVVM-pattern. MVVM wordt gebruikt om het aantal alert filters die bij de klant horen samen met de naam van de klant te kunnen tonen. Voor de alert filters wordt er gebruikgemaakt van een GridControl, ook in combinatie met het MVVM-pattern. Om alle alert filters die bij een bepaalde klant horen op te halen, wordt het klantID gebruikt dat ook in de alert filter is opgeslagen. De GridControl maakt het ook gemakkelijker om alert filters te verwijderen. Bij de twee functies die toelaten om alert filters te verwijderen wordt dezelfde techniek gebruikt. Eerst wordt er een kolom toegevoegd die een checkbox bevat die aanduidt of je de alert filter wil verwijderen (zie figuur 7.2). Deze checkbox is gelinkt met een property van het type boolean in het viewmodel. Als de gebruiker aangeeft dat hij de geselecteerde alert filters wil verwijderen, worden de viewmodel objecten die aangeven dat ze mogen verwijderd worden, opgehaald en verwijderd uit de configuratie. Een tweede handige functionaliteit van de GridControl is dat de gebruiker de gegevens kan filteren door op de kolomhoofding te klikken en een van de keuzes te selecteren. Onderaan kan de gebruiker zien welke filter hij heeft ingesteld en kan hij de filter ook verwijderen. Als laatste voorziet de GridControl de functionaliteit om bepaalde kolommen editeerbaar te maken. Zo kunnen bepaalde eigenschappen van het viewmodel object, dat aan de rij in de GridControl is gekoppeld, aangepast worden.
Hoofdstuk 7. Componenten van de gebruikersapplicaties
55
Figuur 7.2: Alert filters verwijderen
Om de voorwaarden van de alert filter te specificeren wordt een FilterControl gebruikt. Het is een control die niet aanwezig is bij de Windows Forms controls. Het biedt de gebruiker een eenvoudige manier om een filter in te stellen. In ons geval wordt er een filter voor monitoring facts opgesteld. Elke monitoring fact die voldoet aan de filter zal in aanmerking komen om een alert te genereren. Je kan kiezen uit een AND- of een OR-operatie om je filter samen te stellen. Daarnaast kan je kiezen voor operatoren die (on)gelijkheid testen, een interval opgeven of werken met de like-operator zoals in SQL. Voor het ingeven van de voorwaarden kan gebruikgemaakt worden van verschillende controls. Normaal is dit een gewoon tekstvak, maar om het de gebruiker gemakkelijker te maken kan dit worden aangepast. Naargelang het type van de property van de monitoring fact is de control aangepast. Voor ID’s hebben we gebruikgemaakt van een SpinEdit control die enkel cijfers toelaat. Voor properties die veel mogelijkheden hebben in de vorm van een string, hebben we de LookUpEdit control gebruikt. Dit is een combobox die je kan koppelen aan een databron. Deze databron is dan gewoon een lijst van opties waar de gebruiker uit kan kiezen.
Figuur 7.3: DevExpress FilterControl component
De filter die de gebruiker heeft ingesteld, kan opgehaald worden in de vorm van een FilterString of in de vorm van CriteriaOperator object. De FilterString is gemakkelijk omdat die kan worden opgeslagen in een bestand en later terug kan opgehaald worden.
Hoofdstuk 7. Componenten van de gebruikersapplicaties
56
Ook om de filter opnieuw te tonen aan de gebruiker, is het voldoende om de FilterString property in te stellen bij de FilterControl. Daarnaast kan de verzameling van CriteriaOperator objecten omgezet worden naar een LINQ where-clausule. Dit wordt gebruikt in het algoritme (zie 4.2) om de monitoring facts te filteren. Met deze where clausule blijven enkel de monitoring facts over die een alert zouden kunnen genereren. Om de verschillende alert filter extensies te kunnen configureren hebben we twee user controls 1 aangemaakt. Deze user controls bestaan uit simpele componenten die toelaten de eigenschappen van de alert filter extensie in te stellen. Dit op zo’n manier dat de gebruiker niet hoeft te weten hoe de alert filter extensie precies werkt. Om de gebruiker extra informatie te geven over wat de control juist doet wordt er bij elke user control een tooltip voorzien.
Figuur 7.4: Tooltip links onderaan
Voor de configuratie van de e-mail worden er ook verschillende eenvoudige componenten voorzien om de ontvanger(s) van de e-mail te selecteren en het onderwerp en de body van de e-mail op te stellen. Voor de body van de e-mail wordt er gebruikgemaakt van een CheckedListBoxControl. Deze werkt op dezelfde manier als de gewone list box die is vermeld in de eerste paragraaf van deze sectie, maar het voorziet extra functionaliteit om te kunnen controleren welke rijen geselecteerd zijn. Zowel bij het opstellen van het onderwerp als bij het opstellen van de body van de e-mail wordt er een voorbeeld aangemaakt. Voor het onderwerp wordt een niet-editeerbaar tekstvak gebruikt, maar voor de body wordt een RichTextBoxEdit gebruikt. Deze laat toe om HTML te tonen door de HTML-tekst toe te kennen aan de HtmlText property.
7.3
Integratie in Casmir
Casmir is de applicatie die intern bij ICORDA wordt gebruikt. Ze heeft verschillende functies, zoals het connecteren met een server bij een klant of het bekijken van een historiek van monitoring facts voor een bepaalde klant en nog veel meer. De nieuwe functionaliteit van Casmir is het bekijken en configureren van alerts voor de klanten van ICORDA. Dit is namelijk het doel van deze masterproef. 1
user control: een control die uit meerdere controls bestaat, maar wordt beschouwd als een geheel. Deze controls hebben meestal als doel een specifieke taak te vereenvoudigen.
Hoofdstuk 7. Componenten van de gebruikersapplicaties
7.3.1
57
App.structure
Hoe is deze bestaande applicatie uitgebreid? Wat we niet gedaan hebben, is de code van Casmir zelf aanpassen. We zijn van een leeg Visual Studio project begonnen en we hebben ervoor gezorgd dat het op een eenvoudige manier in Casmir kon ge¨ıntegreerd worden. Hiervoor is er een nieuw configuratiebestand gebruikt, nl. de app.structure. Net zoals de app.config is dit een XML-bestand. Dit bestand wordt ingelezen bij het starten van de applicatie om zo de structuur van de applicatie te bepalen. Een volledig voorbeeld kan bij de bijlagen worden gevonden. Hier zullen een aantal stukken besproken worden. De eerste tags die in de app.structure worden gevonden zijn de Pages, de Page en de PageGroup tags. De Pages tag kan meerdere Page tags bevatten en elke Page defini¨eert een tabblad in de toolbar, zoals bij de toolbar van Word, Excel en Powerpoint (versie 2007, 2010 en 2013). De LinkName verwijst naar een Command tag dat in de volgende paragraaf zal worden verduidelijkt. Elke PageGroup staat voor een scheiding in de toolbar. De toolbar ziet er dan uit zoals in figuur 7.5. Listing 7.1: Pages voorbeeld 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
< Pages > < Page > < Title > Casmir FactViewer Title > < PageGroups > < PageGroup > < Title > Alert Viewer Title > < Commands > < CommandLink > < LinkName > AlertViewer LinkName > CommandLink > Commands > PageGroup > < PageGroup > < Title > Alert Configuration Title > < Commands > < CommandLink > < LinkName > AlertFiltersConfiguration LinkName > CommandLink > < CommandLink > < LinkName > UserAlertFilterConfiguration LinkName > CommandLink > Commands > PageGroup > PageGroups >
Hoofdstuk 7. Componenten van de gebruikersapplicaties 25 26
58
Page > Pages >
Figuur 7.5: Toolbar van de FactViewer
De Commands kunnen twee types hebben. Het eerste type is Screen, dan staat het voor een applicatie die zal worden uitgevoerd. De LinkName wordt gebruikt om naar het commando te verwijzen. De DisplayName wordt gebruikt om te tonen aan de gebruiker. De TypeName bevat de naam van de klasse die de volledige view bevat. TypeAssemblyPath bevat het pad naar het DLL-bestand2 , het bestand dat de compiler aanmaakt om het programma te kunnen uitvoeren. Zoals in het voorbeeld te zien is kan een Command van het type Screen ook Commands bevatten. Deze verwijzen naar een Local Command. Dit Command type kan geen andere Commands bevatten. Deze commando’s stellen functies van de applicatie voor. Het commando in het voorbeeld staat voor de functie, die van een bestaand alert filter een template maakt. Het verwijst dus naar een stuk code in de AlertFiltersConfigurationFrm klasse. Listing 7.2: Command voorbeelden 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
< Command > < CommandType > Screen CommandType > < LinkName > AlertFiltersConfiguration LinkName > < DisplayName > Alert Filters Configuration DisplayName > < TypeName > AlertFiltersConfigurationFrm TypeName > < TypeAssemblyPath > Casmir . FactViewer . Data . dll TypeAssemblyPath > < Commands > < CommandLink > < LinkName > CreateTemplateFromCurrentSettings LinkName > CommandLink > Commands > Command > ... < Command > < CommandType > Local CommandType > 2
Dynamic Link Library
Hoofdstuk 7. Componenten van de gebruikersapplicaties 16 17 18 19 20
59
< LinkName > CreateTemplateFromCurrentSettings LinkName > < DisplayName > Maak template van huidige instellingen DisplayName > < TypeName > AlertFiltersConfigurationFrm TypeName > < TypeAssemblyPath > Casmir . FactViewer . Data . dll TypeAssemblyPath > Command >
Figuur 7.6: Commando’s van de Alert Filter Configuration editor
7.3.2
Uitbreiding Casmir
Elke applicatie die is toegevoegd aan Casmir heeft een app.structure bestand gehad. Casmir zelf heeft dus ook een app.structure. Het enige wat nu moet gebeuren is de Page van de FactViewer toevoegen aan de Pages tag van Casmir en alle Commands toevoegen. Nu moeten alle Visual Studio Solutions3 die voor de FactViewer zijn aangemaakt, toegevoegd worden aan de Solution van Casmir. Dan moeten de nodige referenties naar die solutions nog toegevoegd worden, zodat het bestaande Casmir project weet waar hij moet zoeken naar de nieuwe applicaties. Op die manier kan elke nieuwe applicatie onafhankelijk van de Casmir applicatie worden ontwikkeld.
3
Solution: dit is hoe visual studio bepaald welke code bij elkaar hoort. Elke applicatie hoort bij een solution.
Besluit Het resultaat van deze masterproef zijn drie gebruikersapplicaties en een Windows service die met elkaar kunnen samenwerken. De eerste applicatie kan alle gegenereerde alerts op een overzichtelijke manier aan de gebruiker voorstellen. Alerts kunnen hier ook aan bepaalde personen toegekend worden om het probleem op te lossen. De applicatie geeft ook aan welke alerts zijn bekeken en welke niet, en ze kan ook alerts verwijderen. De twee andere applicaties zorgen voor de configuratie van de alerts in de vorm van alert filters. De alert filters worden gebruikt door de Windows service om te bepalen welke monitoring facts alerts moeten genereren. De configuratie-editors laten de gebruiker toe om snel voor een aantal klanten alert filters te specificeren door gebruik te maken van templates. Daarnaast kan elke alert filter apart worden aangepast of worden verwijderd. Ook het verwijderen kan op een snelle manier gebeuren door per klant de alert filters te verwijderen. Een andere manier is globaal alert filters verwijderen en gebruikmaken van de filter(s) die je kan instellen op de kolommen van de alert filters tabel. Een gebruiker kan ook een configuratie voor zichzelf aanmaken. Hier kan hij aangeven dat hij bepaalde voorwaarden wil aanpassen of dat hij geen notificaties wil ontvangen voor bepaalde alert filters. Wanneer de gebruiker de configuratie aanpast zal die ook meteen in werking treden bij de Windows service. Door gebruik te maken van technologie¨en zoals het ADO Entity Framework kan alles in de databank worden opgeslagen. Dit wil zeggen dat de gegenereerde alerts als de verschillende alert filters in de databank worden opgeslagen. Ook DevExpress in combinatie met het Model View ViewModel pattern heeft ervoor gezorgd dat de gebruikersapplicaties meer functionaliteit kunnen aanbieden in minder tijd, dan wanneer deze technologie¨en en dit design pattern niet zouden gebruikt zijn. Ze zorgen voor duidelijkere code die eenvoudiger is aan te passen. Door tijdsgebrek zijn er geen extra taken bijgekomen, die bijvoorbeeld een bepaald probleem zouden kunnen oplossen. Maar de structuur voor deze taken toe te voegen is wel aanwezig. Dit is dan ook een mogelijke uitbreiding op deze masterproef. Er zou bijvoorbeeld kunnen gezocht worden naar manieren om het probleem meteen op te lossen bij de klant, of het oplossen van het probleem meteen toe te kennen aan een medewerker van ICORDA.
60
Lijst van figuren 1.1
Opstelling ICORDA en klanten . . . . . . . . . . . . . . . . . . . . . . . .
4.1 4.2 4.3 4.4 4.5 4.6
Associatie MonitoringFact en Repertor Klassenhi¨erarchie alert filters . . . . . . Klassenhi¨erachie alert filter extensies . Klassenschema voor taken . . . . . . . Klassenschema alert filter configuratie . Structuur gegenereerde alerts . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
8 11 12 13 14 15
5.1 5.2 5.3 5.4 5.5
ADO Entity Framework lagenmodel Structuur entity data model . . . . De entiteiten van het data model . Model View Controller . . . . . . . Schema Model View Viewmodel . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
21 23 27 30 31
6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 6.10 6.11 6.12 6.13 6.14 6.15 6.16 6.17
Treelist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . DataLayoutControl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . GridControl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Niet toegewezen alert . . . . . . . . . . . . . . . . . . . . . . . . . . . . Toegewezen alert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Klanten met alert filter teller . . . . . . . . . . . . . . . . . . . . . . . . Alert filters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . FilterControl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Control voor DateTimeFilterExtension en EqualForDaysFilterExtension Control voor NumberRegexFilterExtension . . . . . . . . . . . . . . . . Stap 1: De ontvanger kiezen . . . . . . . . . . . . . . . . . . . . . . . . Stap 2: Het onderwerp van de e-mail instellen . . . . . . . . . . . . . . Stap 3: De inhoud van de e-mail instellen . . . . . . . . . . . . . . . . . Nieuwe alert filter aanmaken . . . . . . . . . . . . . . . . . . . . . . . . Templates beheren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Alert filters verwijderen . . . . . . . . . . . . . . . . . . . . . . . . . . User alert filters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
41 41 41 42 42 43 43 44 45 45 45 45 46 47 48 48 49
61
. . . . .
. . . . .
2
Lijst van figuren
62
7.1 7.2 7.3 7.4 7.5 7.6
Alle ongelezen alerts . . . . . . . . . . . . . . Alert filters verwijderen . . . . . . . . . . . . DevExpress FilterControl component . . . . . Tooltip links onderaan . . . . . . . . . . . . . Toolbar van de FactViewer . . . . . . . . . . . Commando’s van de Alert Filter Configuration
. . . . . . . . . . . . . . . . . . . . editor
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
54 55 55 56 58 59
1 2 3
Alert Viewer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 Alert Filter Configuration editor . . . . . . . . . . . . . . . . . . . . . . . . 66 User Alert Filter Configuration editor . . . . . . . . . . . . . . . . . . . . . 67
Literatuurlijst [1] Entity Framework Tutorial (2012). Geraadpleegd op 30 mei 2013 via http://entityframeworktutorial.net. [2] Entity Framework Overview (2012). Geraadpleegd op 30 mei 2013 via http://msdn.microsoft.com/en-us/library/bb399567.aspx. [3] Add/Attach and Entity States (2013). Geraadpleegd op 30 mei 2013 via http://msdn.microsoft.com/en-US/data/jj592676. [4] Configuring Relationships with the Fluent API (2013). Geraadpleegd op 30 2013 via http://msdn.microsoft.com/en-us/data/jj591620.aspx.
[5] Hanselman, S. (2010). Creating an OData API for StackOverflow including XML and JSON in 30 minutes. Geraadpleegd op 30 mei 2013 via http://www.hanselman.com/blog/CreatingAnODataAPIForStackOverflowIncludingXMLAndJSON [6] Hanselman, S. (2010). OData Basics - At the AZGroups ”Day of .NET”with ScottGu. Geraadpleegd op 30 mei 2013 via http://www.hanselman.com/blog/ODataBasicsAtTheAZGroupsDayOfNETWithScottGu.aspx. [7] Introducing OData Data Access for the Web, the cloud, mobile devices, and more (2011). Geraadpleegd op 30 mei 2013 via http://msdn.microsoft.com/en-us/data/hh237663.aspx. [8] WCF Data Services. Geraadpleeg op 30 mei 2013 via http://msdn.microsoft.com/en-us/library/cc668792.aspx. [9] Introduction (2013). Geraadpleegd op 30 mei 2013 via http://www.odata.org/introduction/. [10] Implementing the Model-View-ViewModel Pattern. Geraadpleegd op 30 mei 2013 viahttp://msdn.microsoft.com/en-us/library/ff798384.aspx. [11] LINQ (Language-Integrated Query). Geraadpleegd op 30 mei via http://msdn.microsoft.com/en-us/library/vstudio/bb397926.aspx.
63
Literatuurlijst [12] Walkthrough: Creating a Windows Service Application in the Component Designer. Geraadpleeg op 30 mei 2013 via http://msdn.microsoft.com/en-us/library/zt39148a.aspx. [13] Configuring the Data Service (WCF Data Services). Geraadpleeg op 30 mei 2013 via http://msdn.microsoft.com/en-us/library/ee358710.aspx. [14] MVC. Geraadpleeg op 30 mei 2013 via http://www.moock.org/lectures/mvc/.
64
Afbeeldingen van de applicaties
Figuur 1: Alert Viewer
65
Bijlage . Afbeeldingen van de applicaties
Figuur 2: Alert Filter Configuration editor
66
Bijlage . Afbeeldingen van de applicaties
Figuur 3: User Alert Filter Configuration editor
67
Codefragmenten Listing 1: Volledig voorbeeld app.structure 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
xml version = " 1.0 " ? > < A p p l i c a t i o n S t r u c t u r e xmlns : xsi = " http :// www . w3 . org /2001/ XMLSchema instance " xmlns : xsd = " http :// www . w3 . org /2001/ XMLSchema " > < Pages > < Page > < Title > Casmir FactViewer Title > < PageGroups > < PageGroup > < Title > Alert Viewer Title > < Commands > < CommandLink > < LinkName > AlertViewer LinkName > CommandLink > Commands > PageGroup > < PageGroup > < Title > Alert Configuration Title > < Commands > < CommandLink > < LinkName > AlertFiltersConfiguration LinkName > CommandLink > < CommandLink > < LinkName > UserAlertFilterConfiguration LinkName > CommandLink > Commands > PageGroup > PageGroups > Page > Pages > < Commands > < Command > < CommandType > Screen CommandType > < LinkName > AlertViewer LinkName > < DisplayName > Alert Viewer DisplayName > < TypeName > AlertListViewFrm TypeName > < TypeAssemblyPath > Casmir . FactViewer . Data . dll TypeAssemblyPath >
68
Bijlage . Codefragmenten 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
69
Command > < Command > < CommandType > Screen CommandType > < LinkName > AlertFiltersConfiguration LinkName > < DisplayName > Alert Filters Configuration DisplayName > < TypeName > AlertFiltersConfigurationFrm TypeName > < TypeAssemblyPath > Casmir . FactViewer . Data . dll TypeAssemblyPath > < Commands > < CommandLink > < LinkName > CreateTemplateFromCurrentSettings LinkName > CommandLink > < CommandLink > < LinkName > EditTemplates LinkName > CommandLink > < CommandLink > < LinkName > CreateNewAlertFilter LinkName > CommandLink > < CommandLink > < LinkName > DeleteManyAlertFilters LinkName > CommandLink > < CommandLink > < LinkName > QuickDeleteAlertFilters LinkName > CommandLink > Commands > Command > < Command > < CommandType > Local CommandType > < LinkName > CreateNewAlertFilter LinkName > < DisplayName > Nieuwe Alert Filter DisplayName > < TypeName > AlertFiltersConfigurationFrm TypeName > < TypeAssemblyPath > Casmir . FactViewer . Data . dll TypeAssemblyPath > Command > < Command > < CommandType > Local CommandType > < LinkName > CreateTemplateFromCurrentSettings LinkName > < DisplayName > Maak template van huidige instellingen DisplayName > < TypeName > AlertFiltersConfigurationFrm TypeName > < TypeAssemblyPath > Casmir . FactViewer . Data . dll TypeAssemblyPath > Command > < Command > < CommandType > Local CommandType > < LinkName > DeleteManyAlertFilters LinkName > < DisplayName > Verwijder alert filter uit selectie ... DisplayName > < TypeName > AlertFiltersConfigurationFrm TypeName > < TypeAssemblyPath > Casmir . FactViewer . Data . dll TypeAssemblyPath >
Bijlage . Codefragmenten 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
Command > < Command > < CommandType > Local CommandType > < LinkName > QuickDeleteAlertFilters LinkName > < DisplayName > Alert filters snel verwijderen ... DisplayName > < TypeName > AlertFiltersConfigurationFrm TypeName > < TypeAssemblyPath > Casmir . FactViewer . Data . dll TypeAssemblyPath > Command > < Command > < CommandType > Local CommandType > < LinkName > EditTemplates LinkName > < DisplayName > Templates beheren ... DisplayName > < TypeName > AlertFiltersConfigurationFrm TypeName > < TypeAssemblyPath > Casmir . FactViewer . Data . dll TypeAssemblyPath > Command > < Command > < CommandType > Screen CommandType > < LinkName > UserAlertFilterConfiguration LinkName > < DisplayName > User Alert Filter Configuration DisplayName > < TypeName > UserAlertFilterConfigurationFrm TypeName > < TypeAssemblyPath > Casmir . FactViewer . Data . dll TypeAssemblyPath > < Commands > < CommandLink > < LinkName > QuickUserConfiguration LinkName > CommandLink > Commands > Command > < Command > < CommandType > Local CommandType > < LinkName > QuickUserConfiguration LinkName > < DisplayName > Snelle gebruikersconfiguratie DisplayName > < TypeName > UserAlertFilterConfigurationFrm TypeName > < TypeAssemblyPath > Casmir . FactViewer . Data . dll TypeAssemblyPath > Command > Commands > ApplicationStructure >
70