Search  
Friday, February 10, 2012 ..:: Forum ::.. Register  Login
 Forum Minimize
Pentru a putea posta mesaje trebuie să vă înregistraţi.
Notă: Mesajele cu conţinut jignitor sau ilegal (inclusiv cereri de soft piratat) nu sunt acceptate şi vor fi şterse imediat .

Pentru a primi raspunsuri rapide si corecte, scrieti in mesaj ce intentionati sa faceti, ce mesaj de eroare primiti, in ce context si in urma caror actiuni. De asemenea, mentionati versiunea de FoxPro in care lucrati!
Dacă nu specificați versiunea, se consideră VFP 9.0 SP2.

SearchForum Home
  Visual FoxPro  Baze de date, tabele, view-uri si indecsi  Scriere in tabe...
 Scriere in tabela buferata
 
 6/29/2010 4:01:23 PM
User is offlineniculescu.adriana
31 posts


Scriere in tabela buferata
 (N/A)
Am o baza de date deschisa de pe server, optimistic buffering, stabilesc un cod de factura si il scriu in campul cod_fact. Uneori desi codul de factura se calculeaza si e diferit de zero, in campul cod_fact nu imi scrie nimic. Scrierea o fac cu REPLACE TIP WITH V, DATA WITH VDATA, COD_FACT WITH XV si dupa TABLEUPDATE(0,.T.). Toate campurile sunt actualizate numai ala de cod_fact este gol. Care sa fie cauza?
 6/29/2010 4:08:07 PM
User is offlineGrigore Dolghin
3521 posts
www.class-software.eu
1st






Re: Scriere in tabela buferata
 (N/A)
Nu exista nici o cauza logica pentru asta. Eu as cauta in alta parte. De exemplu, nu cumva campurile celelalte sunt scrise deja in inregistrare, iar cand faci replace+tableupdate pointerul de inregistrare e pe EOF?

Grigore Dolghin
Visual FoxPro MVP 2006 - 2010
Class Software
My blog
 6/29/2010 4:09:55 PM
User is offlineniculescu.adriana
31 posts


Re: Scriere in tabela buferata
 (N/A)
Fac Tableupdate imediat dupa replace si instructiunea replace e exact ca cea scrisa inainte. Daca as fi pe EOF nu mi-ar da eroare?
 6/29/2010 4:15:17 PM
User is offlineGrigore Dolghin
3521 posts
www.class-software.eu
1st






Re: Scriere in tabela buferata
 (N/A) Modified By Grigore Dolghin  on 6/29/2010 3:15:56 PM)
REPLACE pe EOF nu da eroare.

Poti sa verifici daca ai intr-adevar o valoare diferita de zero in variabila aia fix inainte de replace? si apoi, imediat dupa replace (dar INAINTE de Tableupdate()), sa verifici daca intr-adevar s-a scris valoarea corecta in camp?

Stii de ce sunt atat de sceptic? fiindca si celelalte campuri sunt populate tot din variabile. Banuiesc ca sunt calculate diferit (de-aia te tot legi de campul de cod factura), dar in esenta sunt 4 variabile care se scriu in 4 campuri, apoi se da un tableupdate. Nu e absolut nicio diferenta intre ele.

Grigore Dolghin
Visual FoxPro MVP 2006 - 2010
Class Software
My blog
 6/29/2010 4:28:44 PM
User is offlineniculescu.adriana
31 posts


Re: Scriere in tabela buferata
 (N/A)
Valoarea variabilei este bine calculata si se scrie imediat dupa in alta tabela care trebuia sa se lege de prima prin acel camp. Si nu se intampla decat uneori, nu mereu. Campul ala e si index unic. Nici eu nu pot intelege ce se intampla. O sa ma uit la fiecare line de cod dar cred ca tine de comunicarea cu serverul sau de cum lucreaza tabela. Programul a mers bine cativa ani dar se lucra multiuser pe un server din reteaua locala, acum scriem datele prin VPN pe un server aflat in alta zona si alt domeniu, banuiesc. Sa fie de aici?
 6/29/2010 4:38:44 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Scriere in tabela buferata
 (N/A)
Index unic sau cheie primara / candidata?
Problema poate fi aici, cheie rejectata iar eroarea "mancata" de un ON ERROR sau de o procedura de tratare a erorii care nu trateaza eroarea si nici nu o afiseaza.
In acest caz, ar trebui sa fie rejectata toata inregistrarea.
Exista un log cu codurile care nu s-au salvat? Au vreo particularitate anume?
Numai analizand codul se poate stabili cauza.

Daca nu se lucreaza cu controale legate de tabela in controlsource, comanda replace+tableupdate poate fi inlocuita cu INSERT INTO si UPDATE.

Daniel Buduru
 6/29/2010 6:11:36 PM
User is offlineGrigore Dolghin
3521 posts
www.class-software.eu
1st






Re: Scriere in tabela buferata
 (N/A)
Dupa cum vezi, si Daniel e de aceeasi parere cu mine - e de la cod, nu de la tabela. Bufferul n-ar avea nici un motiv sa accepte doua valori si sa o refuze pe a treia.

Grigore Dolghin
Visual FoxPro MVP 2006 - 2010
Class Software
My blog
 6/30/2010 9:39:35 AM
User is offlineniculescu.adriana
31 posts


Re: Scriere in tabela buferata
 (N/A)
Am reindexat tabelele si acum testez rezultatul lui Tableupdate mereu. Din nefericire am descoperit ca este posibil sa apara blocaje sau mesajul de Attempting to Lock pe care userii le ignora total, iesind din program si reintrand la loc.
 6/30/2010 5:20:50 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Scriere in tabela buferata
 (N/A)
Atunci e cazul sa revizuiesti strategia.
In loc de a lucra direct pe tabele, fie si bufferate, treci la view sau cursoradapter - tabela va fi blocata doar pe durata salvarii inregistrarilor, si nu pe toata durata editarii.
Utilizeaza tranzactii la salvarea datelor in tabele.
Aloca numerele de secventa (nr factura, etc) in record valid, in interiorul tranzactiei.
Daca utilizatorii au ajuns sa se astepte unul pe altul, e vremea sa treci baza de date pe un server sql.

Daniel Buduru
 7/1/2010 9:04:39 AM
User is offlineniculescu.adriana
31 posts


Re: Scriere in tabela buferata
 (N/A)
Ma intereseaza mai multe despre modul asta de lucru de unde pot citi mai multe informatii? Sa lucrez cu o baza de date de tip SQL si sa o deschid in fox prin conexiune si remote view? Credeam ca va fi la fel de inceata accesarea din cauza foxului.
 7/1/2010 11:01:38 AM
User is offlineDaniel Buduru
2141 posts
1st




Re: Scriere in tabela buferata
 (N/A)
Incet din cauza foxului? Din contra.
Incet este lucrul cu tabele dbf in retea. Fiecare tabela este transferata la utilizator, apoi sunt transferate inapoi inregistrarile modificate.
Fiecare utilizator lucreaza pe o copie a tabelei - ce s-a transferat pe statie. Daca un utilizator modifica tabela, celelalte copii nu sunt actualizate imediat. Un conflict de actualizare este sesizat nu de baza de date de pe fileserver, ci de vfp care ruleaza pe statie si care constata neconcordanta intre copia curenta si copia noua adusa de pe server.
Utilizand index structural cu chei de indexare corespunzatoare filtrelor, transferul se poate reduce, vfp cautand in index pozitia inregistrarilor, apoi transferand numai acele zone din tabela care contin inregistrarile necesare. Tehnologia se numeste Rushmore, a fost inventata de echipa VFP, si este aplicata acum in serverele MS SQL.

Optimizarea unei baze de date este intotdeauna o operatie delicate, dar optimizarea unei baze de date vfp este extrem de delicata.

Daca se foloseste select sql pentru extragerea unui subset de inregistrari, comanda poate fi optimizata rushmore - vezi functia sys(3054).
Din acest motiv este mai eficient lucrul cu view sau cursoradapter (este mai eficient decat view-ul) pentru actualizarea bazei de date.

In cazul unui baze de date SQL, accesul la baza de date se face printr-o singura aplicatie, care ruleaza pe o singura masina - serverul sql. Extragerea inregistrarilor din baza de date se face local, pe masina server, apoi doar subsetul este trimis catre client.

Am dat aici un link la un articol privid realizarea unei aplicatii client vfp - server sql.:
http://www.profox.ro/Forum/tabid/55/mid/374/forumid/12/threadid/31567/scope/posts/Default.aspx#31567

Daniel Buduru
 7/5/2010 5:31:05 PM
User is offlineniculescu.adriana
31 posts


Re: Scriere in tabela buferata
 (N/A)
Multumesc pentru sfat! Mi-am instalat SQLSERVER 2008 Express, am reusit sa imi configurez cursoradapterul dar am o problema. Am o forma in care am un camp "denumire" si un Listbox care afiseaza campul "denumire". Reusesc sa adaug, sa sterg etc dar problema mea consta in faptul ca in Listbox nu reusesc sa ordonez alfabetic valorile, dupa ce adaug o denumire noua. In tabela SQL am facut index "clustered" si este ok dar cum sa afisez si in Listbox ordonat?
 7/5/2010 5:48:33 PM
User is offlineGrigore Dolghin
3521 posts
www.class-software.eu
1st






Re: Scriere in tabela buferata
 (N/A)
Paradigma e diferita si va trebui sa te "rupi" de fox ca sa intelegi corect problema. Indexarea tabelei pe server nu-ti sorteaza automat inregistrarile in cursorul rezultat. Daca vrei sa fie sortate dupa un camp oarecare trebuie sa executi instructiunea Select <campuri> From <tabela> Order By <campul_oarecare>.

Dupa ce adaugi o noua inregistrare in tabela, creezi lista din nou, interogand tabela si descarcand inregistarile afisate in lista in ordinea in care doresti.

Grigore Dolghin
Visual FoxPro MVP 2006 - 2010
Class Software
My blog
 7/5/2010 9:23:20 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Scriere in tabela buferata
 (N/A) Modified By Daniel Buduru  on 7/5/2010 8:25:45 PM)
Soluti este cea indicata de Grig. Trebuie sa aduci inregistrarile de pe server intr-un cursor, ordonat dupa cum doresti.
Pentru asta poti folosi un remote view, un cursoradapter sau o comanda Select executata pe server cu SQLEXEC.
Sa zicem ca vrem sa aducem in listbox inregistrari din tabela articole, ordonate dupa articol.
Sa zicem ca am stabilit o conexiune la server al carei handle il punem in variabila hh.
Sa zicem ca vrem sa returnam rezultatul interogarii in cursorul crslist1
Comanda ar fi asta:
SQLEXEC(hh,[Select articol, idarticol from articole order by articol],[crslist1])

listbox.rowsource='crslist1.articol,idarticol'
listbox.rowsourcetype=6 &&fields

Dar VFP este un mediu de programare facut sa scuteasca programatorul de scris mii de pagini de cod.
Incearca asta:

listbox.rowsource='SQLEXEC(hh,[Select articol, idarticol from articole order by articol],[crslist1])'
listbox.rowsourcetype=3 &&sql statement

Daca ai mai adaugat sau elimita articole in tabela articole, dai comanda

listbox.requery

Asta e tot in ceea ce priveste popularea unui listbox sau combobox cu date de pe un server sql.
Desigur, ramane sa pui numarul de coloane, boundcolumn, columnwidths si ce mai e nevoie, dar, pentru date, sunt suficiente cele 3 linii de mai sus.
Conexiunea se poate stabili in application.init iar connection handle stocat in application.connhandle, sau in dataenvironment.beforeopentables iar connexion handle intr-o proprietate a formului.





Daniel Buduru
 7/5/2010 10:03:53 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Scriere in tabela buferata
 (N/A)
Si inca ceva referitor la lucrul cu baza de date pe un server sql: ar trebui sa uiti de lucrul cu intreaga tabela, atat pentru afisare cat si pentru editare.
Foloseste filtre, astfel incat sa aduci minimum de inregistrari de pe server.
Sa luam drept exemplu un program de facturare.
Aducem o lista de clienti intr-un combobox si filtram clientii dupa data ultimei facturi, sa zicem, ultimele 90 de zile.
Daca nu gasim clientul aiai, cerem toti clientii.
Odata gasit clientul, afisam o lista cu facturile acestui client.
Daca vrem sa editam o factura, aducem heraderul si liniile acestei facturi, facem editarea si salvam.
Cu cat mai putine inregistrari aduse de pe server si cat mai putine campuri intr-o inregistrare, cu atat e mai performanta aplicatia. Inregistrari complete se aduc doar la adaugare/ modificare, niciodata la examinare.
La exemplul din postul precedent, deasupra listei cu articole ar trebui sa fie un combo cu categoriile de articole, iar in lista sa fie afisate doar articolele din categoria aleasa in combo. Desigur, in combo trebuie sa existe si o linie '-Toate categoriile', care sa permita aducera intregii liste de articole.




Daniel Buduru
 7/6/2010 11:56:12 AM
User is offlineniculescu.adriana
31 posts


Re: Scriere in tabela buferata
 (N/A)
Referitor la schimbarea modului de a lucra cu datele observ ca trebuie schimbata abordarea si inca imi este neclar cum voi lucra. Pentru problema de mai sus am facut actualizarea astfel: lc=getcursoradapter() lc.cursorrefresh si este ok. Tipul asta de forma vreau sa il folosesc pentru cataloage de date cu dimensiuni mici pana la 100 inregistrari. Ma gandesc cat de rapid este. Mai exact daca la fiecare adaugare fac o recreare a cursorului nu vor fi intarzaieri mari. Atat de rapid este Select-ul?
 7/6/2010 1:14:36 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Scriere in tabela buferata
 (N/A)
Selectul este mult mai rapid decat crezi.

Nu e nevoie sa limitezi numarul de inregistrari in baza de date, sau sa lucrezi cu tabele mici. De obicei, bazele de date sql au milioane de inregistrari. Rapiditatea cu care se executa comenzile depinde doar de cat de bina este structurata baza de date, de cheile de indexare si de comanda select respectiva.
Lucrand cu SQL Server 2008 Express ai posilitatea de a testa comanda SQL direct pe server. Daca activezi execution plan, vei vedea si daca interogarea este optimizata si vei primi si sugestii pentru optimizarea ei.

Numarul de inregistrari returnate catre o aplicatie se limiteaza in special din cauza traficului in retea, nu din cauza vitezei de executie a comenzii.

Un cursor creat de cursoradapter suporta comenzile pe care le suporta un view: Requery(), Tableupdate(), Tablerevert(). Practic nu ai nevoie sa adresezi explicit metodele obiectului. Orice aplicatie facuta cu view-uri, locale sau remote, poate functiona fara modificari dupa inlocuirea view-urilor cu cursoradapter.

In aplicatiile multiuser e indicat ca actualizarea bazei de date sa nu se faca inregistrare cu inregistrare, ci toate inregistrarile odata.
Am sa iau din nou factura ca exemplu.
Ai o tabela pentru antet factura si o tabela pentru pozitii factura. Faci cate un cursor pentru fiecare, parametrizand comanda sql. Ceva de genul asta:
Select * from facturi_antet where idfactura=?pcidfactura
Select * from facturi_linii where idfactura=?pcidfactura.
Varabila pcidfactura va contine idfactura si trebuie sa fie vizibila in momentul in care apelezi Requery() pe cursorul respectiv
Daca e o factura noua, pcidfactura rebuie sa contina o valoare inexistenta :
pcidFactura='XXXX'
Requery('crsAntet')
Requery('crsPozitii')
Append blank in crsAntet
Append blank in crsPozitii
Daca lucrezi cu controale lagate la cursoare prin controlsourca, poti completa direct datele. Adaugi inregistrari noi in crspozitii dupa necesitati. Daca folosesti un grid pentru asta, pui grid.AllowAddNew=.t.
Acum la salvare.
Inainte de a pune datele pe server, faci verificarea inregistarilor
Verifici daca in crsAntet sunt completate toate campurile oblicatorii. Daca inregistrarea nu este valida, dai un mesaj corespunzator utilizatorului si te introci la editare. Utilizatorul poate fie corecta ce e necesar, fie abandona noua factura - caz in care faci din nou requery pe cele doua cursoare.
Dupa ce crsAntet contine o inregistrare valida, treci la verificarea inregistrarilor din crspozitii. Aici poti sterge - cu tablerevert(.f.) - fiecare linie care nu contine minimul de informatie: idarticol si cantitate. Pentru alte informatii necompletate, poti intoarce mesaj de eroare catre utilizator si revii in editare.
Cand si crsPozitii e valid, treci la completarea campului idfatura din crsAntet, apoi  completezi campul idfactura din crsPozitii cu aceeasi valoare. Daca ai optat pentru o cheie generate pe server, vei aduce cheia dupa salvarea crsAntet si o vei completa in crspozitii inainte de a-l salva.
Abia acum treci la operatie de actualizare a tabelelor.
Deschizi o tranzactie - ai un exemplu in articolul indicat cum se face asta.
Faci Tableupdate pe crsAntet. Daca nu intoarce eroare, actualizezi si crsPozitii.  Daca nu intoarce eroare, inchizi tranzactia cu Sqlcommit, daca ai eroare abandonezi actualizarea cu Sqlrollback - caz in care niciuna din inregistrari nu se salveza in baza de date.
Acest mod de lucru evita aparitia inregistrarilor "schioape" - pozitii fara antet, stocuri neactualizate, si altele.
Este specific lucrului in regim multiuser, indiferent daca este o baza de date vfp sau una sql.


Daniel Buduru
 7/6/2010 4:53:40 PM
User is offlineniculescu.adriana
31 posts


Re: Scriere in tabela buferata
 (N/A)
Pentru moment am lucrat in DataEnvironment cu un cursoradapter cu DataSourceType=ADO. A fost o problema la parametrizarea liniei de select dar am rezolvato. Cand este recomandabil cursorul tip ODBC? In exemplele din documentatia FOX cursorul se creeaza programatic pas cu pas cu "createobject" si atasandu-i proprietati. Cum este recomandabil?
 7/6/2010 5:32:13 PM
User is offlineDaniel Buduru
2141 posts
1st




Re: Scriere in tabela buferata
 (N/A)
ADO lucreaza cu un recordset si este mai lent decat ODBC.
Ca mod de lucru, pot sa-ti dau cateva sugestii.
Mai intai conexiunea.
Ar trebui sa-ti faci o rutina care sa realizeze conexiunea la server, shareable, si sa o memoreze intr-o proprietate.
Daca folosesti un obiect aplicatie, poti sa-i pui o proprietate in care sa memorezi connection handle returnar de rutina de conectare. mai poti folosi o proprietate a obiectului _screen.
Poti face o clasa dataenvironment, care sa apeleze in  o rutina de conectare / deconectare in BeforeOpenTables, clasa pe care sa o utilizezi in formurile tale, sau poti scrie codul direct in dataenvironment.beforeopentables.
Daca faci o conexiune in obiectul aplicatie si o stochezi in obiect sau in _screen, in rutina de conectare din dateenvironment deschizi o conexiune shared pe acelasi connection handle. Daca nu exista, realizezi conexiunea direct.
Important este ca, in momentul cand se executa dataenvironment.opentables, conexiunea sa existe.

Pentru cursoradapter, e comod sa creezi cate o clasa pentru fiecare tabela care trebuie actualizeaza si sa pui aceste clase intr-o biblioteca. Poti folosi cursoradapter builderul in class designer. Poti face mai usor toate setarile necesare. Daca ai o conexiune la server, builderul are acces la tabele si poate asista crearea comanzii select, lista de campuri actualizabile si altele.
Obiectele cursoradapter dintr-o biblioteca nu pot fi puse direct in form.dataenvironment in design time. Poti face o clasa dataenvironment, in care aduci obiectele necesate, si pe care o indici in form.declass si form.declasslibrary.
Sau poti scrie cod in form.dataenvironment.beforeopentables pentru a instantia fiecare cursoradapter in dataenvironment.
Sau, pur si simplu, le poti pune fie direct in form, fie intr-un bussinessobject pe care il pui in form in desing time sau il instantiezi in runtime.

Daca optezi pentru CA instantiate in form, si lucrezi cu cu controale databound, poti folosi proprietatae formului bindcontrols=.f. si comanda bindcontrols=.t. in form.init, evitand in acest mod erorile la instantierea controalelor atunci cand cutrsorul referit in controlsource nu exista inca.

Daca optezi pentru CA in DE, vei avea de rezolvat problema parametrilor. Daca folosesti o variabila drept parametru, variabila trebuie sa existe in momentul in care se executa cursoradapter.cursorfill si cursoradapter.cursorrefresh. Variabilele publice nu sunt o optiune viabila. Poti folosi proprietati ale formului sau ale CA pentru asta, cu observatia ca proprietatile formului nu sunt vizibile pentru decat dupa ce se executa form.load. In acest caz, pui dataenvironment.autoopentables=.f. iar in form.load dai comanda dataenvironment.opentables.

Daca ai lucrat cu view-uri deschise in dataenvironment, e mai comod sa lucrezi la fel si cu cursoradapter. Cand vei trece la bussinessobject - daca vei trece - va fi mai comod sa pui CA in BO, sa pui in BO toate metodele necesare pentru aducerea, verificarea si salvarea inregistrarilor.

Daniel Buduru
  Visual FoxPro  Baze de date, tabele, view-uri si indecsi  Scriere in tabe...

Search  Forum Home         

 Google Ads Minimize

    

Copyright 2002-2010 Profox   Terms Of Use  Privacy Statement