Speedy Tilgang til FoxPro data fra Delphi

Tilgang FoxPro data ved hjelp av hastigheten på Rushmore i Delphi. Delphi DeveloperJanuary 1 999
Copyright Pinnacle Publishing, Inc. Alle rettigheter reserved.Speedy Tilgang til FoxPro data fra Delphi Steve Zimmelman
Når Borland annonserte at Delphi 3 ble nødt til FoxPro DBF /CDX drivere, var det noen spenningen fra FoxPro utviklere som ble forsøker å migrere sine applikasjoner til Delphi. Spenningen var kortvarig, men når de innså at sjåførene ikke har samme slag som sitt eget søskenbarn. Den lille OLE DLL presentert i denne artikkelen kan være broen som endelig bringer de to together.I nylig utviklet en applikasjon for vårt selskap i Delphi tre som leser tabellene i vår FoxPro DOS eldre system. Alt gikk fint i beta, så vi begynte å distribuere programmet til våre kunder. Det var imidlertid en forglemmelse. Vi har aldri testet systemet mot tabeller som ble høyt befolkede. Da vi installerte programmet på en av våre største kundesider, falt søknaden i kne og døde. Problemet: The BDE forsøkte noen komplekse spørringer ved hjelp av lokal SQL mot en tabell som hadde ca 2 millioner plater i den. Vår klient informert oss om at henvendelser ble tatt så mye som 72 timer å fullføre. Dette var selvfølgelig ikke akseptabelt, så jeg begynte å undersøke alternative måter å kjøre spørringer. Resultatet ble en Visual FoxPro (VFP) OLE-objekt i form av en DLL som kjører spørringene (eller nesten alle FoxPro kommando) fra Delphi, transparent, og med hastigheten på Rushmore. Ved hjelp av denne teknologien, spørringen tid falt fra timer til seconds.For de som ikke er kjent med Visual FoxPro, den har en funksjon som kalles Macro Bytte, som er grunnlaget for OLE DLL. Makro Innbytte behandler innholdet i en minnevariabel som en bokstavelig tegnstreng. Når et tegn (&) står foran en streng type minne variabel, er innholdet av variabelen behandlet akkurat som en hånd-skrevet kommandoen, og er executed.The kode for VFP OLE DLL er faktisk veldig enkelt, og kan inneholde så lite som en enkelt prosedyre eller funksjon. Jeg valgte å skrive noen prosedyrer som var spesifikke for programmet, men også inkludert noen generiske de som kan brukes av et program. For enkelhets skyld, har jeg tatt bare de generiske prosedyrer og funksjoner i koden under. ***************************** ********** Program: VFP_OLE.PRG * Visual FoxPro 5 OLE DLL ***************************** ********* DEFINE CLASS VFP_OLE_Server AS CONTAINER OLEPUBLIC Prosedyre Init * Framgangsmåten INIT er automatisk * henrettet når DLL er lastet. Set Snakk Off Set Sikker Av På Feil Do Ole_Err Med Feil (), linjenr (), Message (), Program () Sett Exclusive Off Set Null På ****************** *********************** * - Hvis CPDIALOG er PÅ og en DBF som var * - skapt uten en kodesiden åpnes, * - kodesiden Dialog Box vil konfrontere * - brukeren. ***************************************** SET CPDIALOG AV * Set Behandle Til 1 * * Flytt FoxPro hovedskjermen vei ut til bit-bøtte * så det vil ikke bli sett på om det er gjort synlig. Flytt Window Screen Å -1000, -1000 Endre Window Screen Title "VFP OLE" Hide Window Screen EndProc Prosedyre SetDir Parameter cDir Bruk standard til (m.cDir) EndProc Funksjon ExeSql Parameter cSql Private nRecs, i, cFile, cFileSrc, cFullPath ,; cDestpath, cAlias, IsVFPFile ,; cDbfFileName, nHandle lIsVFPFile = .F. cFullPath = Set ('FullPath') * * Vis Hoved VFP Window slik fil * dialogboksen vil være synlig * hvis VFP ikke kan finne en fil som * er nødvendig for SQL-kommandoen. * Vis Vindu Screen * * - Execute SQL Statement - * * cSql = AllTrim (m.cSql) & cSql * Hide Window Screen * nRecs = _Tally * Sett FullPath På cFileSrc = DBF () Bruk ****** ******************************** * - Sjekk TABLE. * - Hvis Type Er Visual FoxPro Konvertere * - til Fox2x. * - Det BDE støtter ikke VFP tabeller ************************************** nHandle = FÅpne (m.cFileSrc) Hvis nHandle < > -1 LIsVFPFile = (fgets (m.nHandle, 1) = Chr (48)) = fclose (m.nHandle) Endif Bruk (m.cFileSrc) Eksklusiv cDestPath = venstre (dbf (), rotte ('\\', dbf ( ))) Hvis m.lIsVFPFile * - Konverter Resultat Å Fox2x Format - * cFile = 'T' + høyre (sys (3), 7) Kopier til (m.cDestPath + m.cFile) Type Fox2x Bruk Erase (m .cFileSrc) Hvis File (Venstre (m.cFileSrc ,; Len (m.cFileSrc) -4) + '. FTP') Erase (Venstre (m.cFileSrc ,; Len (m.cFileSrc) -4) + '. FTP . ') Endif Rename (m.cDestPath + m.cFile +' DBF '); TO (m.cFileSrc) Hvis File (m.cDestPath + m.cFile + 'FPT.') Rename (m.cDestPath + m.cFile + 'FPT.'); TO (Venstre (m.cFileSrc ,; Len (m.cFileSrc) -4) + 'FTP.') Endif Bruk (m.cFileSrc) Exclusive Endif * - Gjenopprett FullPath Setting - * Sett FullPath & cFullPath ** - - Return Resultat Record Count - ** Return (m.nRecs) EndFunc Prosedyre SetPath Parameter cPath Set Path To (m.cPath) EndProc Prosedyre FoxCommand Parameter cCMD & cCMD EndProc Funksjon FoxFunction Parameter cFunc Private RTN RTN = & cFunc Return ( m.Rtn) EndFuncENDDEFINEProcedure Ole_Err ** - Handle DLL interne feil - ** Parameter nErr, nline, cMessage, cPRG IF (m.nErr = 1 707) * - CDX ikke til stede, OK å Forsøk - * Forsøk Else messagebox (m.cMessage + Chr (13) + Chr (13) +; 'Feil #' + str (m.nErr, 5) + Chr (13) +; 'At Line #' + Str (m.nLine, 5) + Chr (13) +; 'I' + m.cPrg + chr (13) + Chr (13) +; 'Se Fil: OLE_ERR.TXT for detaljer.';, 16, 'FEIL i VFP_OLE.DLL Module') * * - Dump Minne og Filstatus til tekstfil. * Lag Markør OleError (ErrText M (10)) Listen Status NoConsole til fil OLE_STAT.TMP List Memory Som * NoConsole til fil OLE_MEM.TMP Tilføy Blank Erstatt ErrText Med; Replikere ('*', 80) + Chr (13) + Chr (10) +; DTOC (Date ()) + '' + Tid () +; Chr (13) + chr (10) +; PadC ('STATUS', 80, '*') +; Chr (13) + Chr (10) Tilføy Memo ErrText Fra OLE_STAT.TMP Erstatt ErrText Med Chr (13) + Chr (10) +; PadC ("minne", 80, '*') +; Chr (13) + Chr (10) Addi Tilføy Memo ErrText Fra OLE_MEM.TMP Erstatt ErrText Med Chr (13) + Chr (10) +; PadC ('- End Error -', 80, '*') +; Chr (13) + Chr (10) Addi Hvis File ('OLE_ERR.TXT') Kopier Memo ErrText å OLE_ERR.TXT Addi Else Kopier Memo ErrText å OLE_ERR.TXT Endif Erase OLE_STAT.TMP Erase OLE_MEM.TMP * Nær data Hide Window Screen * - Det AVBRYT kommandoen fører Delphi * - for å være i stand til å felle feilen. Avbryt * EndifEndProc *: EOF (VFP_OLE.PRG) Etter at DLL er kompilert, må den registreres hos regsvr32.exe, som distribueres med Windows95 og NT, og bør være i \\ Windows \\ System katalog for Windows95 og \\ Windows \\ System32 for NT. Imidlertid kan denne prosessen automatiseres ved Delphi applikasjonen under kjøring. (se funksjon RegisterDLL) I Delphi program jeg laget en metode som forsøker på å bruke DLL under kjøring, og en annen for å registrere DLL hvis instantiation metoden mislykkes. I tillegg har jeg 2 globale variabler: vFoxOle og bIsFoxOle. vFoxOle er en variant som peker til OLE objekt og bIsFoxOle er en boolsk som forteller programmet hvis OLE-objektet ble vellykket instansiert. Denne måten jeg kan skrive søknaden til å håndtere FoxPro data med VFP OLE eller BDE. Du må også ha en referanse til ComObj i "Bruker" klausul i den formen som instantiates den DLL.In skjemaets skape metode, jeg kaller funksjons IsFoxOle på å bruke OLE DLL. Den Delphi funksjon CreateOleObject () brukes til å opprette en forbindelse til OLE objektet og returnerer en peker til det objektet som er lagret i den variable vFoxOle. CreateOleObject () brukes sammen med en streng parameter som peker til Classname som blir instansiert. I dette tilfellet navnet på DLL er VFP_OLE og klasse er VFP_OLE_Server. Så for å lage en forbindelse brukte jeg CreateOleObject ('VFP_OLE.VFP_OLE_Server') prosedyre TfrmFox.FormCreate (Sender: TObject);. Begynner Hvis ikke IsFoxOle deretter begynne RegisterDLL; //Initial bIsFoxOle med resultatet //av oppretting forsøk. Hvis OLE //objektet ble registrert, så resultatet vil //vil være sant. bIsFoxOle: = IsFoxOle; Avslutt Else bIsFoxOle: = true; End, Function TFrmFox.IsFoxOle: Boolean; Begynn Prøv //instantiate OLE objekt vFoxOle: = CreateOleObject ('VFP_OLE.VFP_OLE_Server'); Resultat: = true; Unntatt Resultat: = False; Enden, enden, Prosedyre TFrmFox.RegisterDLL; //Hvis regsvr32.exe finnes RegisterDLL () //vil se etter VFP_OLE.DLL //i 2 steder: //1) \\ Windows \\ System //2) gjeldende directoryvar A : Array [0..100] av Char; sSysDir: String; sCurDir: String; Begynn GetSystemDirectory (A, 100); sSysDir: = A; sSysDir: = AddBS (sSysDir); sCurDir: = AddBS (GetCurrentDir); Hvis FileExists (sSysDir + 'regsvr32.exe') Deretter begynner Hvis FileExists (sSysDir + 'VFP_OLE.DLL'), og start WinExec (pChar ('»' + sSysDir + 'regsvr32.exe»' + '»' + sSysDir + 'VFP_OLE.DLL" /s), SW_SHOWNORMAL); Avslutt Else Hvis FileExists (sCurDir + 'VFP_OLE.DLL'), og start WinExec (pChar ('»' + sSysDir + 'regsvr32.exe»' + '»' + sCurDir + 'VFP_OLE.DLL" /s "), SW_SHOWNORMAL); Slutt; Avslutt Else Begynn Raise Exception.Create ('Kan ikke registrere VFP_OLE.DLL!'); Enden, slutten; Praktisk bruk
Anta at du har en faktura program, og du trenger å vite hvor mye penger du skylder, alder, og hvem som skylder det. Søket skjema kan kanskje se slik ut: (Insert File: QForm1.BMP her) Når brukeren klikker på OK-knappen, SQL-setning dynamisk opprettet og sendt til DLL som et parameter for behandling. Det er viktig å merke seg at SQL strengen har en "Into Table" som en del av setningen. Uten dette har Delphi applikasjonen ingen måte å plukke opp resultat data. Det er 3 måter du kan håndtere etableringen av tabellen: 1) Lag tabellen på brukerne lokal Temp-katalogen med en statisk filnavn. 2) Skriv en funksjon som skaper et unikt filnavn eller bruke Windows API-funksjonen GetTempFileName (). 3) Kombiner både 1 & To og skape et unikt filnavn i Windows Temp-katalogen. For nettverksmiljøer, finner jeg at alternativ 3 er den tryggeste. Det er like viktig å bruke metoden SetDir () før og etter Query utførelse. Dette er så FoxPro vet hvor finne tabellene det blir spørres mot, og så Delphi applikasjonen kan finne det er veien hjem. Hvis du ikke gjør det SetDir () etter spørringen, så er det en ganske god sjanse for at Delphi applikasjonen ikke vil være i stand til å finne eksterne komponenter som; AVI, BMP, eller WAV-filer den trenger. Dette er fordi FoxPro fysisk endrer katalog pointer.This eksemplet foruts de DBF tabellene er i samme katalog som Delphi kjørbar. Funksjonen GetTempDir () er en enkel wrapper funksjon som bruker Windows API for å få windows temp-katalogen. SQL Velg uttalelsen er dynamisk opprettet basert på Days Past Due, og resultatet bordet er opprettet i Windows Temp direcotry i en fil kalt MyQuery.dbf. Etter MyQuery.dbf blir opprettet, blir den Table1 objektet tildelt dens innhold og vises i grid.procedure TfrmFox.btnExeQueryClick (Sender: TObject); Var sSQLText: String; iRecs: Integer; sAppDir: String; begynne Hvis bIsFoxOle deretter begynne //Få søknad katalogbanen sAppDir: = ExtractFilePath (Application.ExeName); If (e_PastDue.Text = '') Så e_PastDue.Text: = '0'; sSQLText: = 'Select Client.Name,' + 'Invoice.AcctNo, Invoice.Balance,' + '(Date () - Invoice.Date) Som Age' + 'From Client, Faktura' + 'Hvor' + '(Client .AcctNo = Invoice.AcctNo) Og '+' (Date () - Invoice.Date) > = '+ e_PastDue.Text +' Order By Client.Name, Age "+" Into Table '+ GetTempDir () +' MyQuery '; //Kontroller at tabellen objekt som leser //resultatet er lukket før spørringen //utføres. Hvis Table1.Active deretter begynne Table1.Close; //Sørg tabellen blir slettet etter nær Table1.DeleteTable; Slutt; //Tildele midlertidig filnavn til Table1 Table1.TableName: = 'MyQuery.DBF'; //Tildele midlertidig Directory til Table1 Table1.DatabaseName: = GetTempDir (); //Sett VFP standardkatalog til der //Fox dBFS er lagret. vFoxOle.SetDir (sAppDir); //Execute Query iRecs: = vFoxOle.ExeSql (sSQLText); Label7.Caption: = IntToStr (iRecs); If (iRecs = 0) Så MessageDlg ('Ingen registreringer funnet I Query!', MtInformation, [mbOK], 0) Else Begynn //ExeSql () forlater resultattabellen åpen //slik at du kan forhånds prosessen bordet //VFP før Delphi Åpner den. //Disse avskriftene brukes til å endre //sorteringsrekkefølgen ved å klikke på //Grid tittel. vFoxOle.FoxCommand ('Index På Name Tag Name'); vFoxOle.FoxCommand ('Index På Age Tag Age'); vFoxOle.FoxCommand ('Index På AcctNo Tag AcctNo'); vFoxOle.FoxCommand ('Index On Balance Tag Balance'); vFoxOle.FoxCommand ('Lukk Database'); Table1.Open; Slutt; Avslutt Else Begynn MessageDlg ('VFP_OLE.DLL ikke startes!', MtError, [mbOK]); Slutt; //Hvis bIsFoxOleend; Med denne DLL har du muligheten til å gjøre fra i Delphi, nesten alt du kan gjøre fra innenfor FoxPro. Det er ikke bare begrenset til enkle Macro Bytte, men kan brukes til å utvikle Delphi grensesnitt som utnytter hele Visual FoxPro database struktur. Nå er jeg ikke noe som tyder på at vi alle begynne å bruke Visual FoxPro for våre tilbake-ender, men det gjør en fin bro for de av oss som er trekkende våre DOS og Windows-programmer fra FoxPro til Delphi og trenger hastigheten på Rushmore.There er noen av advarsler til denne teknologien bruker Visual FoxPro du bør være klar over:

Feilhåndtering er begrenset. Hvis en SQL-setning refererer til en tabell som FoxPro ikke finner, åpnes det en dialogboks som ber brukeren om banen av den mystiske tabellen. Først etter Escape-tasten trykkes vil det generere en trappable feil. Så det kan være klokt å sjekke for eksistensen av tabellene med Delphi funksjons FileExists (), før du utfører søket.

  • De spørringsresultatene er ofte returneres i Visual FoxPro filformat, gjør noe Delphi ikke Java støtte. Resultatsettet må konverteres av DLL som kan ta ekstra tid å behandle.
  • Det er 2 Visual FoxPro runtime DLL-filer som må distribueres med Delphi program som legger ca 3,9 Mb til den totale størrelsen på applikasjon.

    For å lovlig distribuere Visual FoxPro runtime DLL-filer eller opprette OLE DLL, må du eier en kopi av Visual FoxPro Professional versjon 5 eller greater.Changes Siden denne artikkelen ble WrittenVisual FoxPro versjon 6 og større do ikke arbeide med DLL. Du må kompilere COM-objektet til en EXE. EXE kan registreres ved å åpne den en gang på datamaskinen som skal få tilgang til det. Regsvr32.exe er ingen lang nødvendig.