Page 3 of 10 FirstFirst 1 2 3 4 5 ... LastLast
Results 31 to 45 of 144

Thread: Business Objects - het begin.

  1. #31
    Delphi & OO in Vlaanderen SamWitse's Avatar
    Join Date
    Sep 2007
    Location
    Brussel
    Posts
    833
    Peter,

    Ik heb je post met je eerste zip-file grondig bekeken en getest.
    Daarna heb ik je indrukwekkend document diagonaal gelezen: het bevat de code in je eerste post met heel wat uitleg, maar ik denk niet dat er iets aan de code gewijzigd is.
    Het is een mooie cursus over persistent business objects. Toch heb ik één opmerking:

    Er zit een tekortkoming in je struktuur.
    Je maakt mooie getters en setters om data van Tklant-objecten te mappen naar een tblKlant tabel in je database.

    In die getters en setters kan ik data ÔÇÿmanipulerenÔÇÖ. Dat mag, dat is zelfs de bedoeling. Als de data van een Tklant-object niet exact hetzelfde is als wat er in de database staat, dan zijn de Get* en Set*-methods in Tklant DE plaats om de omvorming uit te voeren.

    Maar wat doe je nu met BDGrid1 op je form? Die link je met de datasource DtsKlant.
    DtsKlant krijgt, in de FormCreate handler, als dataset
    Code:
      DtsKlant.Dataset:= FKlant.Data; 
    Dit is rechtstreeks de TADOQuery.

    Kort gezegd, de DBGrid die je op je form tekent, link je rechtstreeks aan je database-tabel. Dus data haal je op ZONDER via je Tklant.Get*-methods te gaan.
    Dus wat heb ik aan dataconversie in je Get*-methodes?

    Als voorbeeld heb ik gesteld dat de gemeentenaam in Tklant de gemeentenaam uit de database moet zijn, gevolgd door ÔÇÿ(B)ÔÇÖ. Dit schrijf ik, zoals het de bedoeling is, in

    Code:
    function TKlant.GetGemeente: string;
    begin  
    Result:= GetF('Gemeente')+'(B)';
    end;
    Helaas wordt er in mijn DBGrid op het scherm nog steeds gewoon de gemeentenaam afgebeeld zonder ÔÇÿ(B)ÔÇÖ, terwijl in mijn object Tklant wel degelijk de ÔÇÿ(B)ÔÇÖ wordt toegevoegd.

    De hele opzet van deze thread is net om data uit Business Objects (zoals Tklant) te gebruiken in je GUI. En dit lukt hier niet.

    Daarom moet je volgens mij ofwel een eigen Grid maken die Tklanten kan verwerken, ofwel moet je Tklant, of in jouw geval TDBCustom, inheriten van Ttable (of TADOQuery), zodanig dat je een TDBGrid kunt blijven gebruiken.
    Should array indices start at 0 or 1? My compromise of 0.5 was rejected without, I thought, proper consideration.

    Sam Witse.
    Delphi & OO in Vlaanderen

  2. #32
    senior member PeterVercruysse's Avatar
    Join Date
    Nov 2006
    Location
    Rijsel
    Posts
    1,608
    Sam,

    Ik fungeer hier enkel als de schrijver van de handleiding en kan je daarom ook niet onmiddellijk antwoorden.

    Omdat dergelijke zaken moeilijk uit te leggen zijn, heb ik mij voorgenomen om heel eenvoudig te beginnen ( met de basistechnieken ) en deze dan verder uit te bouwen door er steeds meer elementen aan toe te voegen.

    Bij de systemen die ik ken, kun je ondermeer @runtime kiezen voor BDE, ADO, dbExpress, ... wat betekent dat de vorm van abstractie zeker een stuk groter is.
    Attached Files Attached Files
    Last edited by PeterVercruysse; 01-Dec-07 at 01:08.
    Gras groeit niet sneller door er aan te trekken

  3. #33
    De gegeven voorbeelden zijn voorbeelden van het principe, niet van de techniek.

    In werkelijkheid zit de techniek nog iets anders in elkaar. Daar gaat met TdbCustom gaan afleiden van een light memory-dataset. Ik zal moeten nazien om een voorbeeldje te maken, maar het probleem hierbij is dat het component dat ik nu gebruik een commercieel produkt is, en dat kan ik niet op een forum plaatsen.

    Bij data-abstractie gaat het er over om onafhankelijk van eender welke bron ( database, tables, XML, of wat dan ook ) te gaan werken. In dit geval is de enige mogelijke optie om te werken met een dataset in het geheugen. Borland/Codegear is later tot dezelfde conclusie gekomen en heeft met zijn dbExpress trouwens dezelfde weg ingeslagen.

    Het probleem ontstaat wanneer je gaat werken met verschillende databanken ( in de ruime zin van het woord ). Hierbij zijn hoe-dan-ook een aantal verschillen. Ik som er een aantal op:

    1. De veldnamen kunnen anders zijn. Een voor de hand liggend probleem is waarbij in sommige systemen de lengte van de veldnamen beperkt is, bijvoorbeeld tot 8 karakters. Soms zijn ze case-sensitive, ... Ik ken zo'n situatie waarbij de veldnamen per land worden vertaald, maar ik moet er bij vertellen dat dit zeker niet mijn idee is.

    2. Veldtypes die verschillen. Sommige veldtypes zijn bezonder handig, maar bestaan bij het ene systeem en bij het andere systeem niet. Soms moet je char-types gaan trimmen, ...

    3. Bij sommige databanken zijn er optimalisaties mogelijk ( zoals batch-verwerking ), andere databanken hebben dit niet

    4. ....

    De data wordt hier op een vier-tal plaatsen gemanipuleerd.

    1. Door middel van typecasting en aliassen op de databank.

    SELECT CustoNo AS KlantNr, Name AS NAAM FROM customer WHERE ....
    Code:
    procedure SetKlantNr( value: string);
    
    begin
      SetF('CustNo', value);
    end;
    2. Door middel van code die geschreven wordt tussen de 'Query' en de Mem-dataset.

    1+2 samen noemt men de Mapping. In zo goed als alle systemen die daarop gebaseerd zijn, gebeurt dit automatisch ( statisch, dynamisch of iets tussenin )

    Vanaf de mem-dataset, kunnen er ook nog een aantal zaken gebeuren.

    3. De voorstelling van de data kan aangepast worden door het visueel framework. Een typisch voorbeeld hier zijn de typische afrondingen van reals, het tonen van datums ('Maandag 6 september 2007') en dergelijke dingen meer.

    4. De properties. Ook daar kunnen manipulaties gebeuren. Properties naar calculated fields zijn hier een typisch voorbeeld. Deze berekeningen kunnen ook elders uitgevoerd worden, maar dit kan ook door gebruikt te maken van properties. Meestal zijn deze read-only.

    Twee voorbeelden:
    Code:
    property RecordCount: integer read GetRecordCount;
    
    function RecordCount: integer;
    
    begin
      Result:= XGetValue('SELECT Count(*) FROM TblKlant', 0);
    end;
    Deze property is readonly, uiteraard.

    Code:
    property Naam: string read GetNaam write SetNaam;
    
    
    function GetNaam: string;
    
    begin
      Result:= FamilieNaam+ ', '+ VoorNaam;
    end;
    
    procedure SetNaam( Value: string)
    begin
      FamilieNaam:= Copy(Value, 1, Pos(',', Value)-1);
      VoorNaam   := Copy(Value, Pos(',', Value)-1, length(Value));
    end;
    Ik hoop dat dit ongeveer het antwoord is op je vraag.
    Last edited by rik.osstyn; 01-Dec-07 at 14:30.
    De verbazing begint waar de kennis ophoudt

  4. #34
    senior member PeterVercruysse's Avatar
    Join Date
    Nov 2006
    Location
    Rijsel
    Posts
    1,608
    Ik zal moeten nazien om een voorbeeldje te maken, maar het probleem hierbij is dat het component dat ik nu gebruik een commercieel produkt is, en dat kan ik niet op een forum plaatsen.
    Ik ben ondertussen bezig met een mem-datasetje te schrijven. Dit blijkt goed te lukken, behalve de widestrings. De voorbeelden ( met handleiding ) zullen volgen.
    Gras groeit niet sneller door er aan te trekken

  5. #35
    senior member PeterVercruysse's Avatar
    Join Date
    Nov 2006
    Location
    Rijsel
    Posts
    1,608
    Sam,

    Hier volgt dan terug een deel van de handleiding, met een voorbeeldje, hopelijk met het antwoord op je vraag.

    Indien ze compleet afgewerkt is, probeer ik ze wel volledig op het forum te krijgen.

    De mem-dataset kan trouwens nog geoptimaliseerd worden, dat doe ik later wel.
    Attached Files Attached Files
    Gras groeit niet sneller door er aan te trekken

  6. #36
    Ik ben net begonnen met de conversie van BDE naar ADO, en ben momenteel dit hier aan het lezen. Zijn BDE naar ADO conversies hiermee eenvoudiger ?

  7. #37
    Delphi & OO in Vlaanderen SamWitse's Avatar
    Join Date
    Sep 2007
    Location
    Brussel
    Posts
    833
    Neen,
    De manier waarop je toegang verschaft tot je data, via BDE of ADO doet er niet veel toe.
    Hier wordt er verder bekeken hoe je je business objects (klassen die die zelf definieert in je applicatie) kunt wegschrijven in een (BDE- of ADO-) database.

    Doet er mij aan denken: Een duidelijke probleemdefinitie is het volgend schema:

    GUI -- GUIDataSet -- Business Objects -- TTable -- Database.

    Tot nogtoe werd/wordt er de relaties tussen BO en Database besproken, terwijl er toch een grote nood is om ook een GUIDataSet (=een dataset waaraan je je data-componenten, zoals TEdit, TDBGrid, van je GUI koppelt) in je business objects te voorzien. [Voor wie nog kan volgen..]
    Should array indices start at 0 or 1? My compromise of 0.5 was rejected without, I thought, proper consideration.

    Sam Witse.
    Delphi & OO in Vlaanderen

  8. #38
    Christophe
    Join Date
    Jan 2004
    Location
    Belgium, West-Vlaanderen, Nieuwkerke
    Posts
    459
    Allemaal goed maar hoe gaan we dan te werk als men at runtime nieuwe velden aanmaken in de database.
    Die zitten dan niet in mijn Business Objects.

  9. #39
    hoe gaan we dan te werk als men at runtime nieuwe velden aanmaken in de database.
    Dat doe je normaal gesproken ook niet runtime.

  10. #40
    Ook daar kan je business objects mee om laten gaan. Is ook niet zo heel moeilijk.
    We adore chaos because we like to restore order - M.C. Escher

  11. #41
    Hoe het technisch allemaal in zijn werk gaat, hangt in principe af van systeem tot systeem.

    Oudere systemen ( zoals AOL e.a. ) maken eerder gebruik van de componenten van Delphi om de layer uit te bouwen. De meer recentere ( en geavanceerdere ) systemen zoals OPF gaan daarin een stuk verder en gebruiken eigen technieken om contact te leggen met de databank.

    De meeste systemen werken met een soort Memory-datasets in RAM waarop het systeem draait. Via andere ( Query ) - objecten worden de gegevens in de RAM gelezen en dan zou ik het schema eerder zo tekenen:

    GUI -- Business Objects -- MemoryDataSet -- TTable/TQuery -- Database.

    Ik verklaar mij nader:
    De gegevens van de GUI worden gecontroleerd door de Business Objects die de gegevens doorgeven aan de MemoryDataset. Van daaruit gaan de gegevens naar de Database.

    Maar eigenlijk klopt dit schema ook niet helemaal, want de business objects kunnen ook de data gaan manipuleren tussen de TTable en de Memory-dataset ( zoals het toevoegen van Calculated fields, hernoemen van velden, ... ).

    Allemaal goed maar hoe gaan we dan te werk als men at runtime nieuwe velden aanmaken in de database.
    Ik denk dat er hier een tweetal zaken door elkaar gebruikt worden. In principe is het zo dat:
    1. Runtime nieuwe velden aanmaken gebeurt in de Mem-datasets, niet in de databank. Deze velden worden aangemaakt door de BO.
    2. Door de code-generator worden zowel de tabellen in de databank als de code voor het programma gegenereerd. Dit gebeurt in design-time.

    Ik weet niet of het dat is wat je bedoelt ?
    De verbazing begint waar de kennis ophoudt

  12. #42
    Ik denk dat Business Objects en MemoryDataset in feite dezelfde laag is.
    Je hebt wat mij betreft
    GUI -- Business Objects -- (Database Abstraction?) -- Database
    Instanties van de business objects hebben al een eigen kopie van de data die ze kunnen manipuleren en erop reageren. Je Business Objects bevatten dus eigenlijk de meeste intelligentie.
    De data behorende bij zo'n BO moet worden opgeslagen. Dit kan een database zijn in de breedste zin des woords. Desnoods dus ook een textfile, inifile of een eigen binary format, al hebben dat soort dingen doorgaans niet de voorkeur.

    Database Abstraction heb ik daarom tussen haakjes toegevoegd. Als je je BO generiek genoeg wilt opzetten, dan heb je wellicht een laag nodig die je BO kan opslaan in een database. Dat kan dus de vorm van een TTable of TQuery hebben, maar vaak zal daar nog meer bij komen kijken. Ik kan me voorstellen dat er nog een extra objectlaag is die alleen een TTable of TQuery gebruikt voor de opslag, maar verder gaat door de database structuur af te schermen voor de BO's. Deze laag kan ook zorgdragen voor het aanpassen van de database structuur, indien dat nodig is.
    Daarbij kun je aan die abstractie laag misschien ook wel een database driver, zoals ODBC of ADO rekenen. Die drivers kun je namelijk al wel tot de database rekenen, maar je komt dan wel in een grijs gebied. Specifieke componenten (TADOQuery, TODBCQuery) horen er dan eigenlijk ook bij, aangezien die database specifiek zijn, en eigenlijk zou je zelfs de SQL-queries daarbij moeten rekenen, aangezien die ook vaak database specifiek zijn, zelfs als je je houdt aan de veel te beperkte ANSI 92 standaard voor SQL.

    Om het plaatje dus rond te maken.
    ~ GUI
    Deze levert visuele input en output voor de gebruiker. De GUI is alleen bekend met de interfaces van de BO's
    ~ Business Objects
    Hierin zit de volledige intelligentie. Ook afhankelijkheden en oorzaak/gevolg zijn hierin vastgelegd. Eventueel kan een BO dit ook gedeeltelijk afdwingen door triggers of constraints te maken in het datamodel.
    ~ Abstraction layer
    Dit is een tussenlaag die de data van business objects vertaalt naar een database en andersom. Dit om de intelligentie van je applicatie onafhankelijk te maken van de onderliggende database.
    ~ Database
    Het daadwerkelijke opslagmedium. Een redelijk domme laag, afgezien wellicht van wat simpele constraints, en natuurlijk referentiele integriteit.

    Overigens hoeft de scheiding niet in concreto zo te liggen. Je kan een deel van je intelligentie bijvoorbeeld onderbrengen in stored procedures. Dit kan een overweging zijn als je hiermee bijvoorbeeld een grondige performance winst kunt halen, of als een deel van functionaliteit ook via een andere interface uit te voeren moet zijn, bijvoorbeeld vanuit nachtelijke jobs, scripts, andere applicaties. Deze intelligentie is dan echter nog wel onderdeel van een BO of eventueel van de abstraction layer (afhankelijk van wat het doet) en dient ook zo behandeld te worden.

    Overigens zou ik er niet voor kiezen om run-time je database model te wijzigen. De applicatie mag ervanuitgaan dat de database structuur in orde is, en mag falen als dat niet zo is. De structuur kun je handmatig aanpassen en vastleggen in scripts.
    1+1=b

  13. #43
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,357
    Voor mijn gevoel: Business objects zijn de OO laag, een dataset is de DA (data access) laag, het relationele gedeelte. Dus zeker niet BO.

  14. #44
    Christophe
    Join Date
    Jan 2004
    Location
    Belgium, West-Vlaanderen, Nieuwkerke
    Posts
    459
    De gebruiker heeft een applicatie met een basisstructuur.
    Voorbeeld: Fiche klanten met velden (naam, voornaam, telefoonnr)
    De gebruiker wilt een tweede telefoonnr.
    Is het dan niet interessant om in de klantfiche een tab te hebben met velden dat de gebruiker zelf heeft aangemaakt.

    Nog een voorbeeld:
    Men heeft een applicatie die iets onderhoud (gasketels, auto, ...)
    Bij een garagehouden zal uw onderhoudfiche over autos zijn.
    Bij een andere gebruiker die gasketels onderhoud is zijn fiche heel anders dan deze met de autos.

    Dan kan men enkel specifieke velden toevoegen volgens de gebruiker. Dus niet in de design maar in run-time of heb ik het mis.

  15. #45
    @cra

    Na mijn mening haal je metadata en data door elkaar.
    Met jou voorbeeld voor een tweede telefoonnummer heb ik eerder volgend model in gedachten:

    Code:
    Klant
      KlantID
      Voornaam
      Achternaam
    
    KlantTelefoon
      KlantID
      TelefoonType
      TelefoonNummer
    Waarbij type dus telefoon1, telefoon2, mobiel, fax, ... kan zijn.

    Runtime toevoegen van velden (in de database dan) kan zelden de bedoeling zijn na mijn mening.

    Groeten,
    Arno
    Nederlandse Firebird Nieuwsgroep
    Hoe meer je weet, hoe meer je beseft hoe weinig je weet.

Page 3 of 10 FirstFirst 1 2 3 4 5 ... LastLast

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •