39
Tags:
delphi
Skrevet af
Bruger #123
@ 26.11.2003
Databaser
Vi må nok starte med at skrive lidt om Delphi og databaser. Der er adskillige muligheder inden for database support i Delphi, jeg vil starte med at gennemgå de mest almindelige.
Man skal i øvrigt være opmærksom på at man fra Delphi 5 kun har database support i Professional og opefter. Den sidste "personal" edition af Delphi som har database support er Delphi 4 Standard.
BDESiden Delphi 1 har Delphi direkte supporteret databaser i gennem en teknologi som hedder BDE. Det står for Borland Database Engine.
Det er et abstraktionslag som lægges ind imellem databasen og Delphi og fungerer ved at abstrahere fra de forskelle der er på de forskellige databaser. Måden man forbinder til en Interbase database og en Microsoft Access database er meget forskellige f.eks. Typisk bliver det dog brugt sammen med Paradox tabeller som er et filbaseret database system der er indbygget i bl.a. Windows. Paradox er dog et gammel system, og lider derfor under nogle begrænsninger i funktionalitet som man ikke ser i nyere systemer.
Problemet med BDE er at den har et forholdsvis stort footprint, det er en installation på adskillige Mb, ikke noget man ønsker at inkludere i sin installation hvis man regner med sætte sit program til download. Ud over at man også skal sørge for at installere selve database serveren...
Se iøvrigt mere her:
http://info.borland.com/devsupport/bde/Fordele: Når først det er sat op, er det meget let at arbejde med.
Ulemper: Stort footprint, besværligt at sætte op. Kræver ekstern database system.
DBExpressFra omkring Delphi 6 barslede Borland med en ny måde at tilgå databaser på. Den metode hedder DBExpress under et, og består reelt at et par ini filer og en dll eller to til hver database engine (en database engine er den mekanik der reelt får databasen til at fungere). Dvs. at metoden udmærker sig ved et relativt lille footprint.
Man skal stadigvæk sørge for at der er en database server tilgængelig på maskinen, men er der det så fungere denne metode udemærket. Problemet med den er at der kun følge support til ganske få databaser med delphi. Professional understøtter Interbase og MySQL. Enterprise understøtter endvidere DB2, Oracle og vist nok MS SQL Server.
Man kan så downloade ekstra drivere, der er adskillige rundt om på nettet, men de fleste koster penge.
Fordele: Lille footprint, let at sætte op.
Ulemper: Eksterne filer der skal inkluderes. Drivere koster ofte penge. Understøtter kun uni-directionelle dataset. Kræver eksternt database system.
MyBaseMyBase er et lille filbaseret database system som følger med Delphi, det findes i følgende versioner: Delphi 5 Enterprise, Delphi 6/7 Professional og Enterprise.
MyBase udmærker sig ved at det har et meget lille footprint. Enten inkluderer man en dll (Midas.dll) som fylder ca. 300 Kb, eller også inkl. man en unit i sit program der hedder MidasLib. Denne dcu før ens program til at fylde ca. 200Kb ekstra.
MyBase har nogle begrænsning i forhold til større database projekter. Man har begrænsede muligheder med hensyn til filtrering og udvælgelse af data, men er iøvrigt velegnet til små projekter. Desuden er det fremragende til briefcase modeller, hvor man har en større database, f.eks. en MS SQL database. Her kan man så hente data over i sit dataset, som ligger i hukommelsen og bearbejde det off-line og så opdatere data tilbage på serveren, her er uni-directionelle datset dog kun understøttet.
Alternativt kan man anvende som et selvstændigt database system. Derved får man adgang til bl.a. bi-directionelle dataset og det fungere i det hele taget ganske fornuftigt.
Fordele: Meget lille footprint. Der er ingen eksterne filer, eller database system.
Ulemper: Understøtter kun uni-directionelle dataset ved eksterne databaser. Begrænset funktionalitet.
ADOADO står for Active Data Objects og er en Microsoft opfindelse. Det betyder at man er begrænset til Microsofts egne database produkter. Dog finder der ADO drivere til andre systemer, men ADO drivere til Access f.eks. er faktisk inkluderet i de fleste Windows systemer, ellers kan de downloades ganske gratis fra Microsoft.
ADO kan være lidt besværligt at anvende, men til gengæld kan man rent faktisk anvende dem i Personal editions af Delphi. Det vil jeg ikke berører nærmere i denne artikel, da det vil kræve en artikel for sig selv. I Delphi 6 Professional (og muligvis også Delphi 5) findes der en række komponenter som letter arbejdet ganske betydeligt.
ADO er et godt system, som dog er begrænset til Microsoft systemer, dvs. Access og MS SQL Server. Læs evt. mere her:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ado270/htm/pg_introduction.aspFordele: Findes allerede i de fleste Windows systemer.
Ulemper: Begrænset udvalg af understøttede systemer. Kræver eksternt database system.
Uni-directionelle dataset
Som lovet vil jeg berører emnet uni-directionelle dataset. Dette betyder at et dataset kun kan bevæge sig i een retning når det er åbnet. Skal man skifte retning, skal man lukke datasettet og åbne det igen i den rigtige retning. Det er alletiders til rapportering f.eks., men ikke ret godt til online redigering af data.
og Bi-directionelle dataset
Med et bi-directionel dataset kan man bevæge sig frem og tilbage som man lyster i datasettet uden at skulle lukke og åbne det konstant. Det er mest benyttet til redigerering og visning af online data, men er ikke velegnet til rapportering, da det er noget mere ressource krævende.
Delphi og Databaser
Nu vil vi så i gang med at lave en database applikation i Delphi. Jeg har valgt at anvende MyBase til dette da det er dejligt simpelt at gå til, og så kræver det ikke noget eksternt database system. Denne artikel henvender sig derfor til dem der har Delphi 5 Enterprise, eller Delphi 6 Professional og frem.
Vi vil lave en simpel lille telefon bog hvor vi kan gemme oplysninger om venner og familie med adresser og telefon numre.
Vi starter med at oprette et nyt projekt i Delphi, vi kan f.eks. kalde det "Telefonbog". Så starter vi at placere følgende komponenter på vores form:
1 TMainMenu (Standard), 6 TLabel (Standard), 1 TStatusBar (Win32), 1 TClientDataSet (Data Access), 1 TDataSource (Data Access), 1 TDBNavigator (Data Controls), 5 TDBEdit (Data Controls) og 1 TDBMemo (Data Control). Navnene i paranteser er navnene på de faneblade komponenterne er placeret i komponent paletten.
Vi skal iøvrigt også have sat en TOpenDialog og TSaveDialog på vores form. Dem kalder vi diaOpen og diaSave henholdsvis. De skal lige have sat nogle egenskaber.
DefaultExt = *.cds
Filter = CDS Filer (*.cds)|*.cds
Jeg har valgt den følgende placering af komponenterne:
Opsætningen af menuen ser således ud:
Om du navngiver komponenterne som jeg gør, er fuldstændig op til dig, men det er altid en god ide at give komponenterne sigende navne, så man ikke bliver forvirret. I dette tilfælde er der f.eks. 5 TDBEdit komponenter og man bliver hurtigt forvirret og i tvivl om hvorvidt f.eks. DBEdit3 var telefon, eller mobil.
Det næste vi skal gøre er at definerer vores database. Dobbelt klik på TClientDataSet komponenten. Du får nu et lille vindue frem hvor i man kan definere databasens felter. Det gøres ved at højre-klikke og vælge "New Field". Det frembringer følgende vindue:
Her indtaster man felt navn, navnet på TField komponenten der skal oprettes, felt type og evt. længde på feltet. Vi skal bruge 6 felter:
Navn - Type
tring - Size:50
Adresse - Type:Memo
Telefon - Type: String - Size:20
Mobil - Type
tring - Size:20
Arbejde - Type
tring - Size:20
Email - Type
tring - Size:50
Man kan godt navngive komponenterne, men det er ikke nødvendigt, vi skal ikke bruge dem direkte. Felt oversigten ser nu således ud:
Luk dette vindue og højre-klik på din TClientDataSet. Du får nu en context-menu frem. Her skal du finde det punkt der hedder "Create DataSet" og klikke på det.
Nu skal vi så have nogle bindinger.
Start med at sætte DataSource komponentens egenskab DataSet til at pege på ClientDataSet'et. Vælg dernæst hvert DBEdit felt, DBnavigator og DBMemo og sæt DataSource egenskaben til at pege på TDataSource komponenten, jeg har valgt at kalde den dsAdresser.
Endeligt sætter vi DataField egenskaben på hver komponent til et felt i databasen.
edtNavn.DataField = Navn
mmoAdresse.DataField = Adresse
edtTelefon.DataField = Telefon
osv.
Nu skal vi så til at skrive kode.
Menuen FilerStart med at dobbelt-klikke på menu punktet "Ny adresse bog".
Delphi opretter nu en procedure hvori vi skal have skrevet noget kode.
procedure TfrmMain.itmFilNyClick(Sender: TObject);
begin
cdsAdresser.Close;
cdsAdresser.CreateDataSet;
if diaSave.Execute then
begin
cdsAdresser.FileName := diaSave.FileName;
cdsAdresser.Open;
end;
end;
Det der sker her, er at vi lukker datasettet, laver et nyt dataset og tildeler det et filnavn. Derefter åbner vi datasettet igen, og vupti. Vores telefon er indlæst og åbnet og klar til brug.
Så skal vi have åbnet for mulighed for at åbne og gemme eksisterende databaser.
Dobbelt-klik på menu punktet "Åben adresse bog". I denne procedure skriver vi følgende:
procedure TfrmMain.itmFilerAbenClick(Sender: TObject);
begin
cdsAdresser.Close;
if diaOpen.Execute then
begin
cdsAdresser.FileName := diaOpen.FileName;
cdsAdresser.Open;
end;
end;
Igen lukker vi datasettet. Det medfører i øvrigt at evt. ændringer gemmes i filen så vi skal ikke bekymre os om at huske at gemme filen. Dernæst kalder vi OpenDialog og vælger en fil som tildeles ClientDataSet som derefter åbnes.
Det vi skal bruge Gem Adresse bog til, er faktisk hvis vi vil gemme en database under et nyt navn. Vi dobbelt-klikker på "Gem adresse bog" og udfylder proceduren med det følgende kode.
procedure TfrmMain.itmFilerGemClick(Sender: TObject);
begin
if diaSave.Execute then
begin
cdsAdresser.FileName := diaSave.FileName;
cdsAdresser.SaveToFile;
end;
end;
Vi sætter simpelthen FileName til det valgte filnavn, og gemmer datasettet. Dermed har vi gemt datasettet under et nyt filnavn.
Menuen PosterSå kommer vi til håndtering af poster i databasen.
Udfyld "Ny Post" med den følgende kode.
procedure TfrmMain.itmPosterNyClick(Sender: TObject);
begin
if cdsAdresser.State = dsBrowse then
cdsAdresser.Insert;
end;
Vi checker at datasettet er i en "browse" tilstand, og er det tilfældet kalder vi Insert metoden på datasettet. Hvis vi ikke checker for tilstanden først, risikere vi at kalde f.eks. insert mens vi allerede er i insert tilstand og det vil resulterer i en felt.
"Ret Post" skal udfyldes med denne kode.
procedure TfrmMain.itmPosterRetClick(Sender: TObject);
begin
if cdsAdresser.State = dsBrowse then
if (not cdsAdresser.Bof) and (not cdsAdresser.Eof) then
cdsAdresser.Edit;
end;
Her checker vi først for at dataset er i "browse" tilstand, men vi checker også for at der rent faktisk er data i datasettet. Ved at undersøge om BOF (begining of File) og EOF (End of File) er falske, er vi sikre på at der er data.
Koden for "Slet post" er meget lig "Ret post".
procedure TfrmMain.itmPosterSletClick(Sender: TObject);
begin
if cdsAdresser.State = dsBrowse then
if (not cdsAdresser.Bof) and (not cdsAdresser.Eof) then
cdsAdresser.Delete;
end;
Vi foretager de sammen check, men sletter i stedet for at redigere.
Når vi har indtastet vores data, skal det gemmes. Udfyld proceduren for "Opdater" med følgende:
procedure TfrmMain.itmPosterOpdaterClick(Sender: TObject);
begin
if cdsAdresser.State in [dsEdit, dsInsert] then
cdsAdresser.Post;
end;
Her checker vi for at vi rent faktisk er i en tilstand af redigering inden vi poster ændringerne.
Det samme gør sig gældende for "Fortryd".
procedure TfrmMain.itmPosterFortrydClick(Sender: TObject);
begin
if cdsAdresser.State in [dsEdit, dsInsert] then
cdsAdresser.Cancel;
end;
Her bruger vi så bare Cancel metoden istedet for, for at droppe ændringerne.
Menuen NavigationNavigation i datasettet er meget meget let, i det datasettet giver os alle metoderne, vi skal bare kalde dem.
"Første post"
procedure TfrmMain.itmNaviForsteClick(Sender: TObject);
begin
cdsAdresser.First; // Find første post
end;
"Frem"
procedure TfrmMain.itmNaviFremClick(Sender: TObject);
begin
if not cdsAdresser.Eof then // Hvis IKKE ved sidste post
cdsAdresser.Next; // så gå til næste
end;
"Tilbage"
procedure TfrmMain.itmNaviTilbageClick(Sender: TObject);
begin
if not cdsAdresser.Bof then // Hvis IKKE ved første post
cdsAdresser.Prior; // så gå til forrige
end;
"Sidste"
procedure TfrmMain.itmNaviSidsteClick(Sender: TObject);
begin
cdsAdresser.Last;
end;
Så mangler vi bare en ting, hvordan vi søger i datasettet.
"Find"
procedure TfrmMain.itmNaviFindClick(Sender: TObject);
var
navn : String;
begin
if InputQuery('Navn', 'Indtast navn', navn) then
cdsAdresser.Locate('Navn', navn, [loCaseInsensitive, loPartialKey]);
end;
Den kræver nok lidt mere forklaring end de tidligere. For det første er det bare en simpel søgning hvor man søger på navn. Vi anvender InputQuery som er en funktion i Delphi der forærer os en simpel indtastningsdialog.
Den tager tre argumenter, Caption, Prompt og Value. Slå den op i hjælp for nærmere information.
Hvis den returnerer true har brugeren trykket ok, og vi kan så anvende Value til at søge på. Det gøres med Locate metoden. Denne metode tager tre argumenter:
"KeyFields" som er en semikolon separeret liste over feltnavne der skal søges på.
"KeyValues" som er en liste over feltværdier der skal søges på.
"Options" er et sæt af muligheder man kan sætte. I dette tilfælde har vi sat Options til at inkludere "loCaseInsensitive" og "loPartialKey" hvilket indikere at vi er ligeglade med om det er store eller små bogstaver, og at det indtastede søgedata kan være en del af et ord. Delphi hjælpen har iøvrigt en ganske udemærket gennemgang af hvordan Locate fungere.
AfslutningsvisVi mangler bare een ting for at vi er færdige. Vi skal lige have programmet til at vise os hvor mange poster der er i databasen. Dette gøres meget simpelt ved at vælge ClientDataSet på formen. Gå over på Object Inspectoren og vælge "Events". Her skal vi så dobbelt-klikke på "AfterOpen". I den procedure som bliver skabt derved skal vi kode således:
procedure TfrmMain.cdsAdresserAfterOpen(DataSet: TDataSet);
begin
stbStatus.SimpleText := IntToStr(cdsAdresser.RecordCount) + ' poster';
end;
For at få en nøjagtig status, skal cdsAdresserAfterOpen hændelsen tildeles AfterPost og AfterDelete hændelserne på datasettet.
Det var det
Således anvendes TClientDataSet til en simpel applikation. Man anvende TClientDataSet til mange ting, og det er også muligt at bruge flere dataset samtidigt og derved have mange tabeller. En ting man skal være opmærksom på er at TClientDataSet er et såkaldt "In-memory" dataset. Dvs. at hele tabellen læses ind i hukommelsen, når man åbner datasettet.
Det betyder at har man en tabel med 35 Mb data i, så bruger programmet altså 35Mb eller mere af hukommelsen for at læse datasettet ind. På de fleste nye PC'ere i dag er det ikke det store problem, men det er da noget man skal være opmærksom på.
Kildekoden til adresse bogen som vi bygger i denne artikel kan hentes her:
http://udvikleren.dk/articlefiles/123/Telefonbog.zipGod fornøjelse med TClientDataSet.
Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.
Del også gerne artiklen med dine Facebook venner:
Kommentarer (14)
Flot aktikle om databasen til Delphi og
så med praktisk eksempel. FLOT
Med venlig hilsen
Monie Jacobsen
E-mail: energy@sunwind.dk
Jeg ved ikke omdet er den rigtig vej at stille et spørgsmål.
Hvordan tilføjer man nye New Field.
Har allerede 4 Field.
Mvh
Monie Jacobsen
Hehe nice artikel(får næsten løst til at starte på delphi)
Tjek lige op på dit ADO. Det er nemlig ikke kun begrænset til Microsoft Produkter; men indeholder også drivere til både Oracle og andre almindeligt kendte produkter. Sørg for at have den nyeste MDAC installeret. Derudover mangler der lige en kommentar om at DBExpress ganske vist er Borlands nye svar på en Database Engine eller måske rettere Interface; men at det har været så fejlbehæftet i bla. Delphi 6 og Delphi 7, at det var nødvendigt stort set at skrive det om. Vær også opmærksom, at DBExpress returnerer Unidirectional datasets med mindre det foregår via Clientdataset. Og DBExpress understøtter forøvrigt MS SQL.
Til Bobby: Tak for updaten, jeg var ikke klar over præcis hvilke databaser ADO understøtter. Mht. DBExpress har jeg ingen praktisk erfaring med det, ud over ca. 5 minutters "leg". Jeg nævner som et alternativ til database håndtering. I det hele er der jo kun tale om en generel gennemgang af forskellige måder at anvende databaser på. Hovedformålet er jo MyBase, eller TClientDataSet. Men tak for pointerne.
Jeg fåt denn fejl:
[Fatal Error] Required package 'Crystal' not found
Jeg fåt denn fejl:
[Fatal Error] Required package 'Crystal' not found
ups kom til at opdatere så den kom igen.
> [Fatal Error] Required package 'Crystal' not found.
Ja det beklager jeg. Du skal ind i Project Options og under Packages fanebladet fjerne hakket i "Build with runtime packages". Så burde det virke.
Flot gennemgang, fortsæt venligst, og kom gerne ud i alle kroge af database-progarmmeringen. Det kunne være rart hvis du senere beskriver hvordan man eksporter/importer til CSV fil, samt brug af qrickraport eks.v.
Er godt nok lang tid siden artiklen er skrevet,men er først faldet over den nu. Kan stadig ikke kører selvom jeg beder den om ikke at benytte runtime packages'ne...
File not found: 'Variant.dcu'
den besked får jeg når jeg prøver at compile og kører det.
A helping hand would be much appreciated ;-)
På forhånd tak.
/x-ile
Hvor kan jeg hente Database component til Delphi 6 PE?
Jeg syntes ikke at linket virker ?
Det er en flot artikel du har skrevet! den er fyldestgørende for de fleste der er hjemmeprogramør.
Man skylder ligesom at udbrede kenskaben at der også findes mange andre 3. parts databaser på markedet. I den forbindelse skal opmærksomheden henledes på at de som oftes koster penge, men som oftes er virkilig gode og fleksible.
Jeg har i den tid jeg har programmeret Delphi været hæmmet af, at jeg ved brug af paradoks db skulle installere Borland Database Engine til den PC hvorpå programmet skulle afvikles. Hvis sikkerheden bare var strammet en lille smule, kunne dettte af og til give problemer. Jeg taler naturligvis her om NT4, Win 2000, XP og Vista.
En dag jeg søgte på nettet faldt jeg over et funltions-bibliotek fra firmaet "www.componentace.com". I deres produktoversigt har de bla. et VCL funktionsbibliotek med navnet "Absolute Database". Jeg downloadede en prøve og installerede denn, afprøvede den forskellige demoer der fulgte med. Jeg kunne konstatere at det var lige denne type database jeg havde brug for.
Kort beskrivelse.
Type: Enkeltfil database, lige som
f.eks. access.
Bytes per string field: 64.000 bytes
Bytes per BLOB field: 2 GB
Bytes per index: 64.000 bytes
UNIQUE indexes or
constraints per table: 30.000
Database size: 32 TB (dog afhængig af OS)
Identifier length
(in characters): 255
Locks per connection: 2.147.483.647
Columns per table: 65.000
Rows per table: 2.147.483.647
Tables per database: 2.147.483.647
Bytes per page: 65.536
Pages per database file: 2.147.483.647
Connections per database:
- Multiuser: Maksimun angives ved konfigu-
ration af databasen, op til
2.147.483.647
- Singleuser: 1
Records in transaction: 2.147.483.647
In-memory table size: 2.147.483.647 (dog afhængig af
ram)
Dette var lidt omkring databasens "fysiologiske" egenskaber.
Medfølgende er en rigtigt god Database Editor hvor databasen kan kreeres, lige somdet er meget let at oprette den i source.
Generelt må jeg udtrykke min tilfredshed med den lethed databasen er at arbejde med, Tillige fungere den fint med Quick Report samt FastReport.
Den er kompatibel fra Delphi:
Delphi 4 til Delphi 2007
C++ Builder 4 til C++ Builder 2007
jeg købte i sin tid licens til:
Absolute Database - Multi-User, Edition For Single Developer with Source Code.
Dette ef hensyn til at jeg er alene som programør, med udvikler til ferbruger. pris: $349.00
Nogle vil måske syntes at dette er meget at betale, men efterhånden som jeg udvikler mere og mere, Kan jeg indse at prisen er særdeles rimeligt.
Dette er efter min mening et funktionsbibliotek er kan anbefales.
Med venlig hilsen
Lars Christensen
Næstved
Du skal være
logget ind for at skrive en kommentar.