Sunteți pe pagina 1din 13

Agora News PC Magazine Ro NET Report Ginfo agora ON line PC Concrete Liste de discuii Cartea de oaspei

Versiune i

Aplicaii client-server Visual FoxPro-Oracle. Tabele derivate


Marin Fotache & Ctlin Strmbei Odat cu creterea spectaculoas a dimensiunii BD n VFP, extinderea numrului de utilizatori ai bazei, apare drept imperios necesar trecerea la o arhitectur client-server pe dou sau mai multe straturi. Cel mai la ndemn mod de extindere a aplicaiilor VFP const n pstrarea meniurilor, rapoartelor i formularelor n VFP, dar trecerea bazei de date i, implicit, a unei pri importante din "logica aplicaiei", ntr-un SGBD de tip server de baz de date. Firete, Microsoft recomand migrarea spre SQL Server. Serverul de BD pe care poate fi "deplasat" baza de date Fox poate fi oricare din cele importante (Oracle, Sysbase, Informix, DB2), ct vreme prin mecanismul ODBC conexiunea nu mai este o problem. ODBC, drivere ODBC Open Database Connectivity (ODBC) reprezint o interfa standard care permite unei aplicaii s acceseze date din surse diferite: Oracle, MS SQL Server, DB2, Informix, MS Access, dBase .a. Iniiativa ODBC a aparinut companiei Microsoft, avnd acceptul i concursul firmelor de soft care produc servere BD. Legtura ntre aplicaiile ce exploateaz aceste surse de date i serverele BD se realizeaz prin drivere specifice, care reprezint, n fapt, DLL-uri invocate atunci cnd se solicit accesul la o anumit surs de date. Prin urmare, o aplicaie se poate conecta la oricare surs pentru care exist drivere (vezi figura 1 - Componentele ODBC). Conform inteniilor iniiatorilor, interfaa ODBC definete:

Mesaje

o bibliotec de apeluri de funcii care permit unei aplicaii s se conecteze la o surs de date, s execute fraze SQL i s primeasc rezultatele acestora; o modalitate standard de conectare la o surs (BD) de date extern; o modalitate standard de reprezentare a tipurilor de date.

Mai trebuie menionat c aceast interfa mai permite i recepionarea, tot printr-un mecanism standardizat, a erorilor generate de motoarele diferitelor servere de baze de date care gestioneaz BD surs.

Sintaxa frazelor SQL prin care sunt apelabile sursele de date este (sau ar trebui s fie) conform cu specificaiile standardului SQL-92. Prin urmare, sarcina traducerii specificaiilor SQL-92 n specificaiile proprii serverelor ce gestioneaz diferitele surse de date aparine tot driverelor ODBC. Clientul ORACLE8 i protocolul de conectare NET8 ntr-o configuraie client-server, dialogul dintre cele dou entiti poate fi rezumat astfel: cnd un client trimite o cerere (fraz SQL) ctre un server BD, acesta o recepioneaz, o execut, dup care trimite ca rspuns rezultatul frazei SQL sau erorile care rezult n urma execuiei. O astfel de comunicare simpl i comod ntre clieni i serverele de baze de date este posibil n tehnologia Oracle prin protocolul NET8. Protocolul NET8 se sprijin pe substratul de transport din stiva protocoalelor de reea (TCP/IP, SPX/IPX). NET8 furnizeaz n principal trei funcii de baz care se refer la:

operaiile de conectare ; operaiile privitoare la date (transferul datelor ntre client i server); operaiile legate de excepiile/evenimentele anormale ce pot surveni n cadrul unei sesiuni client-server.

O sesiune de lucru Oracle 8 nu poate fi descris fr a avea o imagine, chiar i sumar, a ceea ce se ntmpl cu cererile clienilor odat ajunse pe maina pe care ruleaz serverul Oracle 8. Rolul esenial n aceast privin l are un serviciu special (n NT) numit Listener. Acesta recepioneaz cererile ce sunt trimise ctre serverul Oracle 8 prin diferitele protocoale de reea i le redirecioneaz (ruteaz) ctre bazele de date, sau mai exact ctre instanele bazelor de date, crora le sunt adresate efectiv. Procedura de conectare a unui client la un server Oracle se reduce n principal la urmtorii pai: 1. Un program sau aplicaie utilizator iniiaz o cerere de conectare trimind numele de utilizator, parola i un nume de serviciu (service name), care poate fi asimilat unui alias al bazei de date destinaie. Acest service name este mapat direct pe un descriptor de conectare (connect descriptor). Maparea cade exclusiv n sarcina protocolului NET8 care va ncerca s o rezolve citind fiierele de configurare care descriu descriptorii de conectare i metoda de rezoluie. 2. Dup ce semnificaia numelui de serviciu este determinat, cererea de conectare este transmis, prin protocolul de reea existent, serviciului Listener de pe maina server a crui adres a fost dedus din descriptorul de conectare obinut prin operaia de mapare descris mai sus. 3. Sesiunea de lucru dintre client i serverul bazei de date nu este ns susinut de ctre Listener, rolul acestuia limitndu-se doar la redirecionarea cererilor ctre instanele bazelor de date crora le sunt adresate. Astfel, cnd

primete o cerere ctre o baz de date, Listenerul creaz un proces server cruia i pred controlul sesiunii deschise ntre server i client. 4. Adresa procesului nou creat este trimis procesului de pe maina clientului. Astfel, cele dou procese (procesul utilizator - care a iniiat cererea de conectare i procesul server) vor comunica direct pe durata sesiunii fr a implica serviciul Listener. Arhitectura funcional a driver-ului Oracle ODBC Driver Oracle ODBC Driver permite aplicaiilor Windows (95 sau NT) s efectueze operaii de scriere (actualizare) sau citire (interogare) n BD Oracle utiliznd software-ul de comunicare proprietar Oracle, NET8. Se asigur, astfel, independena fa de protocolul de transport (TCP/IP, IPX/SPX .a.) a dialogului dintre clienii i serverele ORACLE. Acest driver folosete interfaa OCI (Oracle Call Interface) de pe client pentru a trimite cererile de acces ale aplicaiei i pentru a recepiona rezultatele acestora de la sursa de date invocat. Protocolul de comunicare NET8 este utilizat pentru realizarea legturilor ntre clientul OCI i serverul Oracle. Driver-ul furnizat de Oracle traduce sintaxa SQL proprie interfeei ODBC n sintaxa proprie serverului sursei de date. n momentul n care sursa de date invocat returneaz rezultatul, acelai driver l traduce n sintaxa SQL a ODBC. Arhitectura funcional a mecanismului de comunicare prin Oracle ODBC driver este prezentat n figura 2 - Mecanismul de comunicare prin Oracle ODBC driver Se observ c peste stratul de transport al softului de reea se suprapun componente ale protocolului NET8 pentru care au fost construite adaptoare aferente tuturor protocoalele de reea importante. Dintre componentele arhitecturale ale protocolului NET 8, interfaa OCI i serviciul Listener sunt prezentate n schema de mai sus. OCI constituie primul strat din stiva NET8, iar codul OCI (adic funciile din biblioteca OCI.DLL) conine toate informaiile necesare pentru iniierea i desfurarea dialogului client-server ORACLE, sau, cu alte cuvinte, definete apeluri ctre server pentru:

descrierea coninutului cmpurilor returnate pe baza informaiilor din dicionarul de date, pentru analiza (parse) frazelor SQL din punct de vedere sintactic; deschiderea unui cursor printr-o fraz SQL; executarea frazelor SQL n spaiul de memorie destinat cursorului creat; aducerea (fetch) unei nregistrri sau a mai multor nregistrri n aplicaia client;

nchiderea cursorului.

Aplicaia client utilizeaz o combinaie a acestor apeluri pentru a trimite i executa cereri pe serverul ORACLE. Crearea unei surse de date Oracle prin ODBC S clarificm mai nti la ce ne referim cnd vorbim despre o surs de date sau despre un client ODBC pentru un server BD. n sens larg, o surs de date const din datele (baza de date) pe care un utilizator dorete s le acceseze, plus informaiile necesare pentru accesarea lor, referitoare la sistemul de operare, SGBD i substratul de transport n reea. Clientul poate fi asimilat unei aplicaii care acceseaz date de pe un server utiliznd o interfa corespunztoare. Serverul recepioneaz, proceseaz cererile clientului i transmite rezultatul clientului care a iniiat cererea. Un client ODBC utilizeaz interfaa API a driver-ului ODBC pentru a apela funciile specifice acesteia n scopul transmiterii frazelor SQL ctre serverele de date i recepionrii/primirii rezultatelor acestor cereri. Pentru a crea o surs de date Oracle8 accesibil prin Oracle ODBC Driver trebuie urmai mai muli pai. Mai nti, trebuie apelat administratorul surselor de date ODBC (din Control Panel - ODBC Data Source). Din cadrul de pagin (User/System/File)DataSourceName (diferenierea pe user, system sau file este proprie NT-ului i se refer la domeniul de vizibilitate al sursei de date pe maina respectiv) se alege butonul Add care lanseaz fereastra de dialog Add Data Source. Din lista de drivere ODBC se alege Oracle ODBC Driver (care va fi disponibil odat cu instalarea clientului Oracle pe respectiva main). De regul, exist i drivere pentru Oracle create de Microsoft (care funcioneaz n mare msur identic). Pasul imediat urmtor presupune completarea informaiilor cerute n fereastra de dialog Oracle8 ODBC Setup (sau Microsoft ODBC Driver for Oracle Setup ori Microsoft ODBC for Oracle Setup pentru driver-ele furnizate de Microsoft) - vezi figura 3. Dintre aceste informaii, eseniale sunt cele legate de: Data Source Name, UserId i Service Name (sau Connect String ori Server pentru driver-ele Microsoft). Dup selectarea butonului OK din ultima fereastr de dialog, numele sursei de date se va regsi printre celelalte surse de date disponibile pe respectiva main. Crearea unei conexiuni VisualFoxPro (client Oracle) O conexiune (un obiect de tip connection) poate fi asimilat definiiei unei surse de date stocat ntr-o baz de date VFP. Aceast definiie este utilizat atunci cnd se deschide o sesiune de lucru cu baza de date care este reprezentat prin sursa de date respectiv. Deschiderea unor astfel de sesiuni se realizeaz fie implicit prin remote views (tabele derivate la

distan), fie explicit prin interfaa de transfer SPT (SQL Pass-Through). Figura 3. Fereastra de configurare a driver-ului ODBC pentru Oracle8 Definirea unui obiect de tip connection ntr-o BD VFP va cuprinde o serie de parametri care se refer la specificarea sursei de date pentru care este construit conexiunea VFP, i o serie de parametri care se refer la gestionarea comunicrii/traficului dintre clientul VFP i sursa (baza) de date remote (la distan). Crearea i configurarea unei asfel de conexiuni se poate realiza fie asistat, cu ajutorul Connection Designer-ului, ca n figura 4, fie "manual", cu ajutorul comenzilor CREATE CONNECTION i DBSETPROP (parametrii de configurare ai unui obiect de tip connection se stocheaz n dicionarul bazei de date) - vezi listing 1. Figura 4. Connection Designer pentru crearea legturii VFPOracle1 cu baza de date Oracle numit VINZARI. Legarea VFP cu Oracle, chiar n condiiile n care tabelele bazei sunt, n totalitate, gestionate n Oracle, presupune crearea unei BD. Denumit VFPOracle, baza de date VFP va conine conexiuni (connections) i, eventual, tabele derivate "la distan". Precizarea sursei de date se poate face fie prin indicarea explicit a informaiilor referitoare la: Data source, Userid, Password, Database (selectnd opiunea Data source, Userid, Password), fie prin completarea unui ir de caractere (selectnd opiunea Connection string) care se compune, n cazul driver-ului pentru Oracle, din specificaiile parametrilor: DSN pentru numele sursei de date ODBC, UID pentru identificatorul utilizatorului n a crui schem se gsesc datele ce se doresc a fi accesate, PWD parola utilizatorului, DBQ pentru precizarea bazei de date/serviciului Oracle. n cazul irului de caractere pentru conectare, acesta poate fi construit i automat de sistem prin fereastra de dialog activat la selectarea butonului cu eticheta "" din dreaprta csuei de tip text aferent irului de conectare. Aceste dou modaliti de specificare a sursei de date sunt echivalente i cu comenzile din listing 1: Listing 1. Crearea conexiunii prin program
CREATE CONNECTION VFPOracle1 ; DATASOURCE vinzari ; USERID fotachem PASSWORD fotache DATABASE vinzari sau CREATE CONNECTION VFPOracle1 ; CONNSTRING 'DSN=vinzari;UID=fotachem;PWD=fotache;DBQ=vinzari'

Specificaiile pentru gestionarea comunicrii dintre clientul VFP i baza/sursa de date Oracle se refer n principal la: suport pentru tranzacii, procesare sincron/asincron, modul de lucru batch/non-batch. Tranzaciile sunt gestionate fie automat fie manual cu ajutorul interfeei SPT prin funciile SQLCOMMIT() i SQLROLLBACK(). Modalitile de prelucrare a datelor din sursele/bazele de date Oracle, sincron sau asincron, se refer la modul n care se returneaz controlul aplicaiei dup apelarea unei funcii ce implic trafic ODBC. Modul de lucru batch sau non-batch stabilete modul de execuie al unei funcii care poate returna mai multe seturi de date dintr-o surs de date ODBC (ce-i drept, nu am reuit s convingem Oracle s returneze mai multe seturi de date n urma unui singur apel ODBC cum este posibil n MS SQLServer). Aceste specificaii au mai mare importan cnd se lucreaz cu conexiunile ODBC ntr-un mod mai intim, prin funciile specifice interfeei SPT (SQL Pass-Through). Parametrii privitori la aceste specificaii se pot stabili explicit pentru o conexiune, n dicionarul bazei de date, cu ajutorul funciei DBSETPROP. Prin acest funcie se pot stabili atributele: transactions pentru managementul tranzaciilor, ce poate lua valorile 1 (DB_TRANSAUTO din foxpro.h) sau 2 (DB_TRANSMANUAL din foxpro.h), asynchronous; .f. specific o conexiune sincron, iar .t. una asincron; parametru batchmode setat pe .t. indic o conexiune care lucreaz n modul batch. Tabele derivate "la distan" - remote views Crem o tabel derivat denumit vMateriale prin care n VFP se vizualizeaz i (mai ales) actualizeaz tabela M din Oracle. n listing 2 este prezentat programul de configurare a tabelei derivate la distan, asemntoare celor pentru tabelele derivate locale (vezi PCReport pe iunie 1999). Listing 2. Crearea tabelei derivate la distan vMateriale
* creare vMateriale #include foxpro.h CREATE SQL VIEW vMateriale CONNECTION VFPOracle1 ; AS SELECT * FROM M =DBSETPROP('vMateriale','View','Tables','M') =DBSETPROP('vMateriale.CodMat','Field','KeyField',.T.) =DBSETPROP('vMateriale.CodMat','Field','Updatable',.T.) =DBSETPROP('vMateriale.DenMat','Field','Updatable',.T.) =DBSETPROP('vMateriale.UM','Field','Updatable',.T.) =DBSETPROP('vMateriale.ContStocuri','Field','Updatable',.T.) =DBSETPROP('vMateriale.CantConsum','Field','Updatable',.T.) =DBSETPROP('vMateriale','View','UpdateType',DB_UPDATE) =DBSETPROP('vMateriale','View','WhereType', DB_KEYANDMODIFIED)

=DBSETPROP('vMateriale','View','SendUpdates',.T.)

Parametrul WhereType a fost setat pe valoarea DB_KEYANDMODIFIED. Aceasta nseamn c, la "comiterea" buffer-ului n tabela surs, se verific dac, ntre timp, au fost modificate de la alt staie de lucru, atributul (atributele) din cheia primar i atributele modificate local. Dac da, se declaneaz eroarea Update conflict. Curios lucru, toate valorile din WhereType funcioneaz rezonabil (n general !), nu ns i DB_KEYANDUPDATABLE. Aceast valoare face ca n mai toate mementele de actualizarea a tabelei la distan s se declaneze Update conflict. Nu am gsit o explicaie logic acestui comportament, mai ales c pentru o parte din liniile modificate local, eroarea nu se declaneaz ! Toate proprietile tabelei derivate sunt memorate n dicionarul (containerul) BD. Deschiderea sa se realizeaz obinuit: USE vMateriale IN 0. O atenie deosebit merit ns modul de propagare a modificrilor operate n tabela derivat ctre tabela-mum din Oracle, M. n mod obinuit, o tabel derivat la distan prezint un mod de lucru de tip Optimistic Row Buffering. Aceasta nseamn c modificarea unei linii se "comite" n tabela de baz atunci cnd pointerul VFP al tabelei derivate se poziioneaz pe o alt nregistrare sau la execuia funciei TABLEUPDATE(). Pe de alt parte, actualizarea tabelei derivate pe baza modificrilor de ultim moment aprute n BD Oracle se realizeaz tot prin funcia REQUERY(). n dezvoltarea aplicaiilor este necesar preluarea i tratarea erorilor provocate de ctre tabela derivat bazei de date Oracle. Figura 5 - Semnalizarea violrii cheii primare - ilustreaz un caz de violare (prin vMateriale) a cheii primare tabelei M. Valoarea care se repet pentru CodMat este 11401. Din mesajul afiat se poate observa codul Oracle al erorii (-00001) i locul n care a aprut excepia, respectiv triggerul de modificare a tabelei M (atributul CodMat), trigger de tip AFTER STATEMENT. Problema este: cum prelum ntr-o aplicaie VFP, n partea sa de client acest mesaj, i cum rezolvm problema fr combinaia salvatoare CTRL+ALT+DEL. Soluia vine de la funcia AERROR(). Aceasta plaseaz ntr-un vector cu numele indicat informaii despre ultima eroare produs. Pentru erorile ODBC, fiecare component al masivului conine:
Component Tip i coninut

Numeric. Conine valoarea 1526 (Connectivity error:), indiferent de cauza erorii ODBC

2 3 4 5 6 7

Caracter. Textul mesajului de eroare Caracter. Textul mesajului de eroare ODBC Caracter. Starea curent SQL ODBC Numeric. Numrul erorii preluat de la sursa ODBC Numeric. Numrul conexiunii ODBC Valoarea NULL

Dac, de exemplu, la editarea tabelei derivate vMateriale, n denumirea unui material se introduce o liter mic, n momentul comiterii modificrii se genereaz o eroare care, preluat prin funcia =AERROR(vErr), iniializeaz masivul vErr dup cum urmeaz:
Componenta vErr Coninut

vErr(1) vErr(2) vErr(3) vErr(4) vErr(5) vErr(6) vErr(7)

1526 Connectivity error: [Oracle][ODBC][Ora]ORA-02290: check constraint (FOTACHEM.UP_DENMAT) violated [Oracle][ODBC][Ora]ORA-02290: check constraint (FOTACHEM.UP_DENMAT) violated 23000 2290 1 NULL

n BD Oracle a fost definit, pentru atributul DenMat din tabela M, o restricie (prin clauza CHECK DenMat = LTRIM(UPPER(DenMat))) numit UP_DENMAT prin care valorile acestui atribut pot conine numai majuscule, fr spaii la nceput. Eroarea Oracle declanat la nclcarea acestei restricii are numrul 2290 (check constraint violated). Formular simplu n care este utilizat tabela derivat "la distan" Pentru actualizarea nomenclatorului de materiale reprezentat de tabela M din Oracle, construim un formular simplu, prezentat n figura 6 - Formularul frmMateriale legat prin tabel derivat la BD Oracle n listing 3 ce prezint metoda Init a formularului se deschide i (re)populeaz tabela derivat VFP cu date din tabela de baz din Oracle. Listing 3. Metoda Init a formularului
public vErr (7), a

if !used('vMateriale') use vMateriale in 0 exclu endif select vMateriale requery() if eof() or bof() go top endif thisform.cboDenMat_Refresh thisform.Dezactivare_txt

Combo-box-ul cboMateriale este legat la tabela derivat vMateriale (RowSourceType este 6 - Fields, iar RowSource este vMateriale.DenMat). Csuele de tip text sunt legate direct la atributele tabelei derivate. Metoda cboDenMat_Refresh invocat este cea care afieaz n combo-box cboMateriale valoarea curent din vMateriale - vezi listing 4. Listing 4. Metoda cboDenMat_Refresh
for i = 1 to thisform.cboMateriale.ListCount if allt(thisform.cboMateriale.ListItem(i)) == allt(vMateriale.DenMat) thisform.cboMateriale.ListIndex = i exit endif endfor

Metoda asociat evenimentului Click a butonului OK (cmdOK) este cea care declaneaz transmiterea modificrilor din vMateriale n tabela de baz din Oracle -vezi listing 5. Listing 5. Metoda asociat evenimentului Click pentru obiectul cmdOK
thisform.Scrie_Buffer if !a thisform.txtCodMat.SetFocus else b_ = recno() sele vMateriale requery() thisform.cboMateriale.Requery go b_ thisform.cboDenMat_Refresh thisform.Refresh thisform.Dezactivare_txt endif

Din punctul de vedere al materialului de fa, elementul de maxim interes este metoda Scrie_Buffer prezentat n listing 6. Metoda ncearc s scrie coninutul bufferului VFP (nregistrarea modificat a tabelei derivate) n tabela M din Oracle. Dac operaiunea reuete, variabila a are valoarea TRUE (.T.). n caz contrar, prin funcia =AERROR(vErr) se iniializeaz masivul vErr cu informaii despre eroare. ntruct valorile returnate sunt

diferite, n funcie de cauza erorii, este necesar conversia din valori nule i numerice n iruri de caractere pentru afiare i stocare n tabela TEMP - o tabel utilizat pentru jurnalizarea erorilor de acest tip, creat prin comanda CREATE TABLE temp (nr INTEGER, text CHAR (250)). Listing 6. Metoda Scrie_Buffer
select vMateriale rele all like sir* a = tableupdate() if !a =aerror(vErr) for i = 3 to 7 && conversia in sir de caractere a && ultimelor cinci componentele ale vectorului ii=str(i,1) sir&ii = NVL(vErr(i),"NULL") sir_ = sir&ii if TYPE("sir_") = "N" sir&ii = str(sir&ii,10) endif endfor insert into temp values (1, str(vErr(1),7)) insert into temp values (2, vErr(2)) insert into temp values (3, sir3) insert into temp values (4, sir4) insert into temp values (5, sir5) insert into temp values (6, sir6) insert into temp values (7, sir7)) do case case vErr(1) = 1585 && Update conflict messagebox('Inregistrarea actualizate a fost modificata intre timp de altcineva !') case vErr(1) = 1526 and vErr(5) = 1 and "PK_M" $ vErr(2) messagebox('Se repeta valoarea atributului CodMat!') case vErr(1) = 1526 and vErr(5) = 1 and "UN_DENMAT" $ vErr(2) messagebox('Se repeta valoarea atributului DenMat!') case vErr(1) = 1526 and vErr(5) = 1438 messagebox('Valoarea unui atribut numeric depaseste limitele !') case vErr(1) = 1526 and vErr(5) = 2290 and "CK_CODMAT" $ vErr(2) messagebox('Valoarea atributului CodMat depaseste limita stabilita!') case vErr(1) = 1526 and vErr(5) = 2290 and "CK_CONTSTOCURI" $ vErr(2) messagebox('Contul de materiale e musai din clasa 3 !')

case vErr(1) = 1526 and vErr(5) = 2290 and "UP_DENMAT" $ vErr(2) messagebox('Den. materialului se scrie cu majuscule si fara spatii la inceput !') case vErr(1) = 1526 and vErr(5) = 20015 && extragem mesajul de eroare din exceptia && definita in Oracle messagebox(substr(vErr(3),31,65)) otherwise messagebox('Eroare netratata !') endcase =tablerevert() endif

Eroarea furnizat de "motorul" BD Oracle are n VFP numrul 1526. n secvena de cod prezentat sunt preluate urmtoarele erori Oracle: ORA-00001: unique constraint violated ORA-01438: value larger than specified precision allows for this column ORA-02290: check constraint violated [Oracle][ODBC][Ora]ORA-20015: Pentru acest material exista inregistrari copil in tabela MBC! ORA-06512: at "FOTACHEM.TRG_M_DEL_BEFO_ ROW", line 7 ORA-04088: error during execution of trigger 'FOTACHEM. TRG_M_DEL_BEFO_ROW' Ultima eroare este de tip utilizator (adic definit de noi) i se declaneaz, prin RAISE_APPLICATION_ERROR, n declanatorul Oracle TRG_M_DEL_BEFO_ROW. ntruct eroarea ORA-02290 poate proveni din mai multe restricii, identificarea regulii de validare nclcate i afiarea mesajului adecvat se realizeaz cutnd numele regulii de validare Oracle n textul erorii primit (i preluat n vErr(2) i vErr(3)). Inutil de amintit ct de important este s avem nume distincte pentru regulile de validare (i nu numai), astfel nct la identificare s nu existe ambiguiti. Celelalte metode sunt prezentate n listing 7. Listing 7. Alte metode ale formularului
Metoda asociat evenimentului Click pentru obiectul cmdAbandon tablerevert(.t.) thisform.release Metoda asociat evenimentului Click pentru obiectul

cmdMaterialNou sele vMateriale append blank replace denmat with "MATERIAL NOU", UM WITH "KG", contstocuri with "301", cantconsum with 0 thisform.scrie_buffer requery() go bottom thisform.cboDenMat_Refresh thisform.Refresh thisform.Activare_txt Metoda asociat evenimentului Click pentru obiectul cmdEditare thisform.Activare_txt Metoda asociat evenimentului Click pentru obiectul cmdStergere select vMateriale delete thisform.Scrie_Buffer if a if eof() go bottom else if bof() go top endif endif b_ = recno() requery() thisform.cboMateriale.Requery go min(b_,reccount()) thisform.cboDenMat_Refresh thisform.Refresh endif Metoda Activare_txt thisform.cboMateriale.Enabled=.f. thisform.txtCodMat.Enabled=.t. thisform.txtDenMat.Enabled=.t. thisform.txtUM.Enabled=.t. thisform.txtContStocuri.Enabled=.t. thisform.cmdMaterialNou.Enabled=.f. thisform.cmdEditare.Enabled=.f. thisform.cmdStergere.Enabled=.f. Metoda Dezactivare_txt thisform.cboMateriale.Enabled=.t. thisform.txtCodMat.Enabled=.f. thisform.txtDenMat.Enabled=.f. thisform.txtUM.Enabled=.f. thisform.txtContStocuri.Enabled=.f. thisform.cmdMaterialNou.Enabled=.t.

thisform.cmdEditare.Enabled=.t. thisform.cmdStergere.Enabled=.t.

Obs. Pentru binele i corectitudinea formularului, dup selectarea elementului din combo i acionarea unuia dintre butoanele de actualizare (adugare, editare, tergere), se impune dezactivarea acestui control (cboMateriale). Altminteri, scrierea bufferului nu mai poate fi controlat riguros (ntruct combo-ul este legat direct la tabela derivat care funcioneaz n modul 3- Optimist Row Buffering, orice selectare a unui alt element din combo determin modificarea pointerului tabelei derivate i scrierea bufferului pe disc). Concluzii Extinderea, n timp (i spaiu) a dimensiunii bazelor date face imperios necesar trecerea de la o arhitectur file-sharing la una de tip client-server. n aceast prim parte a materialului dedicat aplicaiilor client-server Visual FoxPro-Oracle a fost prezentat mecanismul ODBC de creare a conexiunilor unei BD VFP la serverul Oracle. Dintre cele dou tehnologii, tabele derivate "la distan" (remote views) i SPT (SQL Pass Trough), prezentul articol s-a oprit asupra primeia, ilustrnd-o cu un formular simplu (i simplist) VFP "legat" la o baz de date Oracle 8.