Objekt data må til slutt bli lagret i en database. Denne artikkelen viser deg how.Persistent ObjectsIn de siste par artikler vi har innført Business Objects og vist hvor enkelt relasjoner kan være representert. Dette forholdet som objektegenskapene er en mer formell (og nøytral) representasjon av relasjonene mellom data enheter som kan være implisitt i databasen design, eller eksplisitte innen databaseskjemaet. Beveger seg bort fra en data-sentriske utsikt over enheter og relasjoner til en mer strukturert, objektorientert utstilling har mange fordeler, men de fleste språk (inkludert Delphi) faller bare for en in-memory objektmodell; objekter har ingen statlig utholdenhet kapasitet med mindre man er gitt for dem.Det er mange design løsninger på dette kravet, og vi har allerede fastslått at virksomheten (problemdomenet) objekter selv bør ikke kommunisere direkte med databasen. En passende design er å ha et annet sett med klasser som eksisterer kun som et objekt grensesnitt til databasen, og vil være ansvarlig for lasting og lagring problem domeneobjekt tilstand. Vårt problem domene objekter vil vite noe om hvordan tilstanden deres er lagret på disken, bare at det er en spesiell klasse som er ansvarlig for denne operasjonen. Business Objects vil gjøre et metodekall på et slikt objekt og delegere arbeid til it.The første beslutning som må tas er å bestemme hvordan de skal kartlegge objekter på et databaseskjema. Selv om en rekke objekt databaser eksisterer, har de fleste bedrifter standardisert på en eksisterende RDBMS som de er komfortable og erfaren. Fremme en utvikling endring til en mer objektorientert tilnærming er vanskelig nok uten å kreve at den typisk stor investering i et høyt utviklet databaseteknologi er kopiert for en ny, ukjent en. Derfor vil denne artikkelen fokusere på kartlegging objekter til en SQL-basert RDBMS, da dette utgjør majoriteten av installerte utviklingssystemer. Det bør imidlertid understrekes at en av fordelene ved vår objektmodellen er at det er helt arkitektur-nøytral og kan brukes på et stort antall ulike database topologier, inkludert ISAM og objektbaserte seg. Mapping objekter til databaser
Det er åpenbart og naturlig at det er en forholdsvis enkel begrepsmessig korrespondanse mellom et objekt og en database tuppel (record). Derfor, når du lagrer objekt stat i et RDBMS en svært vanlig, og praktisk, løsningen er å kartlegge et problem domene klasser til tabeller, objekter poster og eiendommer til felt. Merk at fordi vår database skal lagre objekt stat, må det være en komplett representasjon, og derfor er det sannsynlig at det vil bli flere felter i databasen bordet enn en gitt klasse har offentlige eiendommer. I noen tilfeller kan en offentlig eiendom kan ikke ha en direkte tilsvarende felt, men det generelle prinsippet er å kartlegge en eiendom på et databasefelt av lignende fundamental type (karakter, numerisk, dato etc.) La oss nå utvide våre grunnleggende ramme klasser for å støtte objekt utholdenhet. Våre problem domene objekter (TPDObject) må tillate andre klasser for å tvinge dem til å laste eller lagre en stat. Det finnes en rekke alternative måter å nærme seg denne situasjon; Den ene er å tvinge alle objekter til implisitt redde deres tilstand før de blir ødelagt. I praksis applikasjoner krever en finere grad av kontroll over når objektet staten bør være faste og så vår TPDObject vil få to nye offentlige metoder, Load og lagre. Lagre metoden er parameterless, men vår Load metoden må definere nøyaktig hvilket objekt som skal lastes fra vedvarende butikken. Innenfor rammeverket vårt, er alle problem domene gjenstander som har blitt lagret tildelt en unik ID innenfor en gitt kontekst (dette kan være innenfor objekter av samme klasse, objekter av samme opphav, applikasjonen eller universelt). Vi vil bruke denne ID som en parameter til Load metode for å standardisere på de midler som vi etablerer objekt identitet. Merk at dette er alltid brukes, selv om en spesifikk klasse kan ha en passende alternative "primærnøkkel" -konseptet. Standardisering på et enkelt konsept objekt identitet er nyttig, som vår rammeverket kan bruke denne konsistens å behandle våre problem domeneobjekter i en generisk og polymorfe mote. Noen vil kanskje stille spørsmål ved tilstedeværelsen av en offentlig eiendom (riktignok read-only) som eksponerer en type valgt for lettere å passe innvendige av vårt rammeverk. I praksis er identifisering av objekter ved ID noe som skjer nesten utelukkende innenfor rammen koden og blir sjelden innenfor selve applikasjonslogikken seg selv. Innenfor denne arenaen, er gjenstander håndteres ved hjelp av begreper mye mer kjent for sluttbrukeren, som for eksempel "sett av kundene som heter Smith", heller enn gjennom utviklerrettede abstracts.Having definert publikum metoden grensesnittet på vår TPDObject problem domene klassen vi må nå vurdere gjennomføringen. Faktisk er dette veldig enkelt. Vi har allerede uttalt at virksomheten objektet vet ingenting om hvordan det er lagret, bare at det er et annet objekt ansvarlig for denne oppgaven. Derfor, gjennomføring av våre utholdenhet metoder på TPDObject bare delegere arbeidet direkte til et annet objekt referert i et privat felt. Hver av disse metodekall er parametreres med Self, slik at delegert objektet kjenner som eksempel det er å håndtere. I praksis når et problem domeneobjekt er instruert til å spare (eller last) seg selv, rett og slett instruerer det et annet objekt for å "redde meg". Data Management
oppgave faktisk spare objektet tilstand til en database faller til et sett av klasser i data management lag. Forutsigbart, vil vi ha en klassehierarkiet slik at vi kan gi betydelig database-uavhengig funksjonalitet. Alle våre klasser ansvarlige for dataadministrasjon vil stige ned fra en abstrakt TDMObject klasse. Denne klassen gir en objektbasert, database-uavhengig grensesnitt for databaseoperasjoner. Bestemt database støtte er gitt ved å skape en konkret kommer av denne klassen som gir en tilkobling til databasen til valg ved hjelp av hva teknologien er hensiktsmessig, og i tillegg gir noen basetjenester. Disse basetjenester vil bli helt tilpasset til de spesifikke funksjonene i den aktuelle databasen, og vil bli brukt av applikasjonsavhengige etterkommerne tilpasset for å håndtere en bestemt TPDObject. Denne design ikke diktere de midler som de TDMObjects kommuniserer med databasen motoren: hver database lag står fritt til å velge den mest passende (enkleste /raskeste) teknologien som er tilgjengelig. Dette kan bli ADO for SQL Server 7, IBExpress for Interbase, BDE for Paradox filer, en tilpasset API eller faktisk er det mulig å grensesnittet til noe som ODBC eller CORBA for generisk håndtering. Min preferanse er å optimalisere forbindelsen ved hjelp av en database avhengig sett av komponenter som disse er generelt tilby størst funksjonalitet og hastighet. Vær oppmerksom på at du velger en database avhengig API ikke begrenser din søknad til å kjøre med denne database; Det er mulig å erstatte en database avhengig TDMObject lag for en annen. Grensesnittet til TDMObject er rent objekt basert, så det kan garanteres at gitt våre database lagene gjennomføre konkrete metoder riktig, vil programmet vil kjøre identisk uten changes.The selve gjennomføringen av hver database-spesifikke lag avhengig av databasen bekymret , men generelt for SQL-stand databaser er det verdt å gi en generisk Utfør kommando som tar en gyldig SQL kommando som en parameter. Når vi har en TDMObject kommer for en valgt database må vi gi en rekke etterkommere fra denne klassen, en for hver TPDObject i søknaden vår. Disse vil bli tilpasset for å håndtere en svært bestemt kombinasjon av å spare en bestemt klasse i en bestemt database. Detaljene i disse klassene avhengig av de funksjonene som tilbys av data management klasse for bestemt database, men en funksjon er viktig: Lagre operasjonen må returnere ID av objektet frelst. Grunnen til dette er at i vår valgte modellen, ikke en TPDObject har ikke en ID før første gang den er lagret. En spesiell fordel med denne modellen er at det er veldig enkelt for dataadministrasjon lag for å oppdage om det er nødvendig å generere en INSERT eller UPDATE typen database handling. Vanligvis kan tildeling av ID gjøres av et annet objekt konstruert utelukkende for dette formålet, men det er en svært gunstig optimalisering som kan gjøres hvis vi stole på våre data management objekt å gjøre denne oppgaven for oss. Husk at vår ID må være unikt i en gitt sammenheng; hvis sammenheng valgt er at objekter av samme klasse har unike ID-tallet, da dette kan likestilles med poster i tabellen med unike ID-er. De fleste databaser har noen anlegg for å generere sekvensielle unike ID-er for innsatte poster, og gjøre denne verdien tilgjengelig etter at databaseoppdatering. Ved hjelp av dette anlegget innenfor våre data management lag kan unngå å kopiere innsatsen for å garantere unikhet, og i beste fall kan spare på utenforliggende databaseoperasjoner for å etablere neste tilgjengelige ID. Hvis den valgte databasen mangler slike funksjoner deretter en intern ID tildeler ordning innenfor dataledelseshierarkiet kan være used.Listing 1 viser utvidelser til vår Work enhet for å støtte laste og lagre operasjoner, sammen med omrisset av en klasse til å håndtere data tilgang til en database gjennom ADO. Det forutsettes at ADO forbindelsen er etablert, og at nytte rutiner er gitt i klassen til å utføre SQL-kommandoer og å håndtere tilbake de mottatte data. I denne implementeringen kommer klasser er nødvendig for å overstyre Load metoden, og også å gi et nytt innlegg og oppdatering gjennomføring. Det er ganske lett å se at disse tre metodene skal generere passende SQL-kode og oppdatere objektet fra ResultSet (eller vice versa). Med litt mer innsats er det mulig å plassere mer arbeid innenfor den generiske TADO_DMObject klassen selv, pålegge en mer rigid grensesnitt på kommer klasser som krever mindre gjennomføring. Et eksempel på dette ville være stamfar klassen genererer SQL-kommandoer dynamisk, gitt et sett av eiendoms navn og values.Our klassespesifikke data management objekter (for eksempel TCustomerDM, tilsvarende TCustomer) må ha inngående kjennskap om innvendige av PD objekt som det er ansvarlig. I denne forstand kan de bli sett på som "venn" klasser av problemet domeneobjektet, og i Delphi dette betyr at implementeringer må være i samme enhet. Denne artikkelen problem
Vår design krever en TDMObject skal ytes for hver TPDObject. Hvor og når kan denne bestemmelsen skje? Hva er dette problemet med denne tilnærmingen, og ved å analysere mønster av metodekall til våre TDMObjects, hvordan kan det bli omgått (((Oppføring 1 - Databehandling objekter og grensesnitt))) enhet rammeverket? Interfacetype TDMObject = klasse; TPDObject = klasse privat DMObject: TDMObject; FID: TObjectID; offentlig prosedyre Load (konst ID: TObjectID); prosedyren Lagre; slutt; TDMObject = klasse offentlig prosedyre Load (PDObject: TPDObject; konst ID: TObjectID); virtuell; abstrakt; fungere Lagre (PDObject: TPDObject): TObjectID; virtuell; abstrakt; slutt; TADO_DMObject = klasse (TDMObject); privat FADO: TADOExpress; beskyttede //Funksjoner for å hjelpe etterkommerne til å samhandle med databasen prosedyre Utfør (SQL: String); Eiendommen ADO: TADOExpress lese FADO; //Metoder som etterkommere må gi funksjon Sett (konst PDObject: TPDObject): TObjectID; virtuell; abstrakt; Prosedyren Update (konst PDObject: TPDObject); virtuell; abstrakt; offentlig funksjon Lagre (PDObject: TPDObject): TObjectID; styre; enden, implementationprocedure TPDObject.Load (konst ID: TObjectID); begynne Assert (DMObject < > null, 'No Data Management protestere tilgjengelig'); DMObject.Load (Self, ID); ende; prosedyre TDMObject.Save; begynne Assert (DMObject < > null, 'No Data Management protestere tilgjengelig'); FID: = DMObject.Save (Selv); ende; funksjon TADO_DMObject.Save (PDObject: TPDObject): TObjectID; begynne hvis PDObject.ID = NotAssigned deretter begynne Resultat: = Sett (PDObject); ende annet begynne Update (PDObject); Resultat: = PDObject.ID; end, end, end (((End Oppføring 1))) Neste i serien
.
Vedvarende Objects
Next Page:Fabrikk mønstre for menyen operations