Search  
Monday, December 09, 2019 ..:: 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  Ma roade ceva ....
 Ma roade ceva ...
 
 1/28/2012 8:44:18 PM
User is offlinealemao
344 posts
3rd


Ma roade ceva ...
 (N/A)
Folosesc intr-o baza de date tranzactiile.
La formul de modificare (pentru corectarea unei inregistrari) pe metoda clik a butonului modifica am pus BEGIN TRANSACTION.
Dupa care la inregistrarea curenta se introduce data modificarii si apoi DELETE, urmata de comanda INSERT SQL care introduce o noua inregistrare cu datele corecte.
Apoi se ruleaza
lsuces = tableupdate(0,.t.,"tabela")
IF lsuces
END TRANSACTION
ELSE
ROLLBAK
ENDIF

Precizez ca tabela este bufferata cu 2 si formul se deschide cu datasession 2 - private.
Va intreb, este gresit?
Din recomandarile de pe forum se vorbeste de buffer 5 care nu sunt sigur ca ajuta la o tabela cu peste 150.000 inregistrari, accesata simultan de cel putin 3 useri fiecare de pe statia lui.
Din experienta voastra ce imi recomandati.
 1/28/2012 9:25:42 PM
User is offlineGrigore Dolghin
3996 posts
www.class-software.ro
1st






Re: Ma roade ceva ...
 (N/A) Modified By Grigore Dolghin  on 1/28/2012 9:26:38 PM)
Buffering-ul pe row executa un TableUpdate automat atunci cand se modifica pozitia pointerului de inregistrare. Comanda INSERT SQL muta pointerul de pe inregistrarea stearsa pe inregistrarea nou introdusa, ceea ce are ca efect comiterea comenzii DELETE, indiferent daca INSERT SQL reuseste sau nu.

Treci pe buffering 5. Dimensiunea tabelei nu e relevanta pentru buffering.

In alta ordine de idei: daca vrei sa modifici inregistrarea aia, de ce nu folosesti UPDATE?

Grigore Dolghin
Visual FoxPro MVP 2006 - 2010
Class Software
My blog
 1/29/2012 3:44:48 PM
User is offlineEugen Gliga
2092 posts
1st




Re: Ma roade ceva ...
 (N/A)
Explicatiile sunt foarte clare, dar am si eu niste nelamuriri referitor la o situatie identica.

Daca se foloseste Buffering 5, totul ar fi Ok, dar atunci, fiind vorba doar de o singura tabele, mai are rost folosirea tranzactiilor ?

Referitor la folosirea Update situatia s-ar complica in cazul in care se modifica numarul de pozitii in plus sau in minus. Ar trebui folosit simultan cu Update si un Delete sau Insert.
Poate un CursorAdapter ar rezolva mai bine problema.

Referitor la Buffering 5 am o rezerva in al folosi in astfel de cazuri. In cazul in care mai multe persoane modifica acelasi document ( inclusiv stergeri sau inserari de pozitii ) , rezolvarea conflictului ramane in sarcina programului  si nu este chiar simplu de rezolvat. De exemplu, in mod justificat mai multe persoane modifica, sterg si adauga pozitii in acelasi document. Primul salveaza documentul iar urmatorii sunt pusi in situatia de a alege ce varianta ramane. In unele cazuri solutia corecta este interclasarea modifcarilor, lucru nu chiar simplu de facut. In astfel de situatii as fi tentat sa blochez documentul inainte de a incepe modificare pt a nu permite modificarea simultana de mai multe persoane a aceluiasi document.


 1/29/2012 4:09:37 PM
User is offlineDaniel Buduru
3513 posts
1st




Re: Ma roade ceva ...
 (N/A)
 Eugen Gliga wrote
Explicatiile sunt foarte clare, dar am si eu niste nelamuriri referitor la o situatie identica.

Daca se foloseste Buffering 5, totul ar fi Ok, dar atunci, fiind vorba doar de o singura tabele, mai are rost folosirea tranzactiilor ?

Referitor la folosirea Update situatia s-ar complica in cazul in care se modifica numarul de pozitii in plus sau in minus. Ar trebui folosit simultan cu Update si un Delete sau Insert.
Poate un CursorAdapter ar rezolva mai bine problema.

Referitor la Buffering 5 am o rezerva in al folosi in astfel de cazuri. In cazul in care mai multe persoane modifica acelasi document ( inclusiv stergeri sau inserari de pozitii ) , rezolvarea conflictului ramane in sarcina programului  si nu este chiar simplu de rezolvat. De exemplu, in mod justificat mai multe persoane modifica, sterg si adauga pozitii in acelasi document. Primul salveaza documentul iar urmatorii sunt pusi in situatia de a alege ce varianta ramane. In unele cazuri solutia corecta este interclasarea modifcarilor, lucru nu chiar simplu de facut. In astfel de situatii as fi tentat sa blochez documentul inainte de a incepe modificare pt a nu permite modificarea simultana de mai multe persoane a aceluiasi document.



Si care ar fi legatura intre table buffering si blocrea documentului? Aici e vorba de blocarea optimista - in momentul actualizarii sau de blocarea pesimista - la inceputul editarii, care este independenta de table buffering sau row buffering.
Problema actualizarii concurente nu poate fi exclusa prin nici un mod de abordare, ci doar solutionata intr-un mod sau altul, si anume interzicerea ei sau tratarea conflictului.
Modul de lucru cu un server in backend inseamna absolut intotdeauna atat utilizarea tranzactiilor - in mod implicit, serverul deschide automat o tranzactie, si lucrul cu table buffering, intrucat nici o modificare nu se face direct in server.

O rutina de salvare corect facuta include deschiderea tranzactiei, actualizarea si comiterea tranzactiei sau abandonarea modificarilor.
Editarea - modificare, inserare, stergere - trebuie facuta intotdeauna in afara tranzactiei.
Atunci cand acest proces este pus la punct, nu mai are importanta daca se salveaza modificari intr-o singura tabela sau in 100 de tabele in acea tranzactie. Pur si simplu functioneaza si isi face treaba.

Vfp include un application wizard, pe care, dupa cate vad, extrem de putina lume l-a incercat vreodata, si cu atat mai putini s-au uitat in codul sursa al claselor dimn framework-ul acestei aplicatii. Acest framework a fost facut de aceeasi echipa care a facut si vfp, totusi, cel putin aici, nu i se acorda absolut nici un credit.
E instructiv pentru orice programator sa se uite, macar o singura data, cum au gandit cei care au creat mediul de programare utilizarea lui.






Daniel Buduru
 1/29/2012 5:31:20 PM
User is offlineDaniel Buduru
3513 posts
1st




Re: Ma roade ceva ...
 (N/A)
Chiar daca se actualizeaza o singura tabela, ea poate avea cod in trigger-e care sa afecteze alte tabele. In acest caz, tranzactia asigura integritatea bazei de date, anuland modificarile facute de codul din trigger in cazul abandonarii actualizarii.
Faptul ca, la momentul la care se scrie o aplicatie care utilizeaza acea baza de date, tabela nu are cod in triggere, este nerelevant. Baza de date poate fi modificata ulterior aplicatiei, caz in care aplicatia in cauza poate afecta integritatea bazei de date.

Daniel Buduru
 1/29/2012 5:36:52 PM
User is offlineEugen Gliga
2092 posts
1st




Re: Ma roade ceva ...
 (N/A)
Daniel Buduru wrote


 
Si care ar fi legatura intre table buffering si blocrea documentului? Aici e vorba de blocarea optimista - in momentul actualizarii sau de blocarea pesimista - la inceputul editarii, care este independenta de table buffering sau row buffering.


Pai bufferingul  se ocupa si de blocare pesimista sau optimista, daca am inteles bine. Blocarea pesimista este la nivel de linie si doar in momentul cand incepe editarea asa ca nu ma ajuta foarte mult. Solutia la care m-am gandit este sa folosesc Buffering 5, dar in momentul in care vreau sa modific un document ( ma refer la documente cu mai multe pozitii ) sa blochez manual pozitiile documentului sau doar header-ul, astfel incat alt utilizator sa fie avertizat ca documentul respectiv este in modificare. Nu stiu daca e bine sau nu, a fost doar o idee.

 
Problema actualizarii concurente nu poate fi exclusa prin nici un mod de abordare, ci doar solutionata intr-un mod sau altul, si anume interzicerea ei sau tratarea conflictului.
Modul de lucru cu un server in backend inseamna absolut intotdeauna atat utilizarea tranzactiilor - in mod implicit, serverul deschide automat o tranzactie, si lucrul cu table buffering, intrucat nici o modificare nu se face direct in server.

Nu m-am referit la o solutie client/server. Postul facea referire doar la o tranzactie VFP cu o tabela cu  tableupdate. Intrebarea mea a fost, daca in acest caz mai are rost tranzactia, deoarece un Tablerevert ar rezolva problema.

 
Vfp include un application wizard, pe care, dupa cate vad, extrem de putina lume l-a incercat vreodata, si cu atat mai putini s-au uitat in codul sursa al claselor dimn framework-ul acestei aplicatii. Acest framework a fost facut de aceeasi echipa care a facut si vfp, totusi, cel putin aici, nu i se acorda absolut nici un credit.
E instructiv pentru orice programator sa se uite, macar o singura data, cum au gandit cei care au creat mediul de programare utilizarea lui.


Multumesc de informatii. O sa ma uit si eu prin acest framework.





 1/29/2012 6:14:38 PM
User is offlineDaniel Buduru
3513 posts
1st




Re: Ma roade ceva ...
 (N/A) Modified By Daniel Buduru  on 1/29/2012 6:23:28 PM)
Buffering:
2 – Sets pessimistic row buffering on.
3 – Sets optimistic row buffering on.
4 – Sets pessimistic table buffering on.
5 – Sets optimistic table buffering on

Blocarea pesimista penalizeaza performantele bazei de date. Sunt rare cazurile in care se justifica.
O inregistrare blocata afecteaza nu numai actualizarea ei, ci toate comenzile care opereaza la nivelul tabelei, cum ar fi sum, count,  etc. In acest caz, ceilalti utilizatori trebuie sa astepte eliberarea lock-ului inainte de a obtine informatiile cerute din baza de date. Si daca utilizatorul intra in editare, apoi in pauza de masa ....
Frecventa confilctelor de actualizare nu este asa de mare cand se utilizeaza blocarea doar la salvare fata de frecventa cazurilor in care pe baza de date nu se poate opera din cauza inregistrarilor blocate.

O aplicatie bine facuta ar trebui sa fie independenta de backend-ul utilizat, fie tabele vfp, fie server sql.
 L.E.: Voiam doar sa scot in evidenta faptul ca o baza de date utilizata shared, cum este un server sql, exclude prin constructie actualizarea fara tranzactii.


Daniel Buduru
 1/29/2012 6:55:22 PM
User is offlineDaniel Buduru
3513 posts
1st




Re: Ma roade ceva ...
 (N/A)
In folderul FFC din vfp se gaseste biblioteca _app.vcx.
Obiectul _datasession din _app.vcx contine codul necesar pentru actualizarea inregistrarilor, fara buffering, cu buffering optimistic sau pesimitic, cu sau fara tranzactii, precum si codul pentru revert si altele.

Daniel Buduru
 1/29/2012 10:27:44 PM
User is offlinealemao
344 posts
3rd


Re: Ma roade ceva ...
 (N/A)
Multumesc tuturor pentru sfaturile si ideile exprimate la acest post.

Am facut ceva sapaturi (oups termenul cred ca e "tabu" avand in vedere ce s-a intamplat de curand cu user-ul injurios), si am gasit ceva.
Astfel ca pe langa tranzactii si blocarea tabelei in mod optimistic (5), m-am gandit ca inaintea salvarii sa rulez urmatorul cod (cules dintr-o carte):

DO WHILE GETNEXTMODIFIED(nCurRec) <> 0 && Parcurge ciclic zona tampon
GO nCurRec
RLOCK() && Blocheaza inregistrarea modificata
FOR nField = 1 TO FCOUNT(cAlias)
cField = FIELD(nField)
IF OLDVAL(cField) <> CURVAL(cField) && Compara valoarea originala cu valoarea curenta, apoi ii cere utilizatorului sa rezolve intr-un fel conflictul
nResult = MESSAGEBOX("Datele au fost modificate de un alt utilizator."+CHR(13)+;
+"Salvez modificarile dumneavoastra?",4+48+0,"Inregistrare modificata")
IF nResult = 7 && Daca utilizatorul alege "NO", anuleaza modificarile
TABLEREVERT(.F.)
ELSE
TABLEUPDATE(0, .T., cAlias)
ENDIF
UNLOCK RECORD nCurRec
ENDIF
ENDFOR
nCurRec = GETNEXTMODIFIED(nCurRec)
ENDDO

Dar daca folosesc tranzactiile, atunci in loc de TABLEREVERT() voi folosi ROLLBACK iar dupa TABLEUPDATE() o sa inserez END TRANSACTION.

Totusi, nu inteleg rostul blocarii inregistrarii cu RLOCK() atata vreme cat tabela este bufferata optimistic (cod 5)?
In plus functia GETNEXTMODIFIED() verifica toata tabela daca sunt inregistrari modificate. Ma intreb, inregistrari modificate doar de mine sau de toti utilizatorii? Logic ar fi ca sa verifice doar inregistrarile modificate ce exista in bufferul tabelei asociat form-ului meu care are datasession private , nu?


 1/29/2012 10:32:42 PM
User is offlinealemao
344 posts
3rd


Re: Ma roade ceva ...
 (N/A) Modified By alemao  on 1/30/2012 6:03:12 AM)
 Grigore Dolghin wrote
Buffering-ul pe row executa un TableUpdate automat atunci cand se modifica pozitia pointerului de inregistrare. Comanda INSERT SQL muta pointerul de pe inregistrarea stearsa pe inregistrarea nou introdusa, ceea ce are ca efect comiterea comenzii DELETE, indiferent daca INSERT SQL reuseste sau nu.

Treci pe buffering 5. Dimensiunea tabelei nu e relevanta pentru buffering.

In alta ordine de idei: daca vrei sa modifici inregistrarea aia, de ce nu folosesti UPDATE?


Aha, deci daca folosesc buffering 5 atunci pot lucra linistit cu DELETE urmata de INSERT SQL.
In acest caz problema va fi sa testez daca intre timp valoarea curenta a unui camp nu a fost deja modificata de un alt user mai rapid ca mine.
Codul de mai sus face o verificare in acest sens.
Daca folosesc comanda UPDATE SQL aceasta nu deplaseaza pointerul de la o inregistrare la alta, astfel ca modificarile asupra acelei inregistrari nu sunt comise?
Credeti ca am inteles bine principiul de functionare!?!

Multumesc anticipat.
 1/29/2012 11:54:19 PM
User is offlineDaniel Buduru
3513 posts
1st




Re: Ma roade ceva ...
 (N/A)
In codul pe care l-ai postat RLOCK se foloseste pentru blocarea inregistrarii pana cand sunt analizate toate campurile si se rezolva eventualele conflicte de actualizare.

In majoritatea situatiilor, este mai eficient sa executi mai intai tableupdate si doar in cazul in care se ridica o eroare 1585 - Update conflict - sa treci la analizarea campurilor si la rezolvarea conflictului.
Daca se actualizeaza doar campurile modificate, campuri care pot fi determinate cu GETFLDSTATE si a caror valoare (valoarea din buffer, nu cea data de CURVAL()) difera de OLDVAL(), probabilitatea unui conflict de actualizare se reduce, intrucat sansa ca doi utilizatori sa modifice simulta acelasi camp al aceleiasi inregistrari nu este prea mare.
Cazurile in care doi utilizatori modifica simultan acceasi inregistrare ar trebui sa fie extrem de rare pe o baza de date corect proiectata.
Situatia cea mai frecvent aparuta ar fi, de ex, la facturarea din mai multe puncte pe acelasi stoc. In acest caz, o procedura de rezervare a cantitatii in momentul selectiei unui articol e mai eficienta decat blocare inregistrarii pana la salvarea documentului.

Daca folosesti table buffering (4 - pesimistic sau 5 - optimistic) poti efectua insert / update / delete in cursor, urmand ca toate inregistrarile sa fie actualizate la tableupdate().
Atentie, al doilea parametru din Tableupdate este fortarea actualizarii. Daca este >T> (tableupdate(x,.T.,...) ), chiar daca exista un conflict de actualizare, inregistrarea este salvata in tabela.

Daniel Buduru
 1/30/2012 2:05:53 AM
User is offlineEugen Gliga
2092 posts
1st




Re: Ma roade ceva ...
 (N/A)
 Daniel Buduru wrote
Buffering:
2 – Sets pessimistic row buffering on.
3 – Sets optimistic row buffering on.
4 – Sets pessimistic table buffering on.
5 – Sets optimistic table buffering on

Blocarea pesimista penalizeaza performantele bazei de date. Sunt rare cazurile in care se justifica.
O inregistrare blocata afecteaza nu numai actualizarea ei, ci toate comenzile care opereaza la nivelul tabelei, cum ar fi sum, count,  etc. In acest caz, ceilalti utilizatori trebuie sa astepte eliberarea lock-ului inainte de a obtine informatiile cerute din baza de date. Si daca utilizatorul intra in editare, apoi in pauza de masa ....
Frecventa confilctelor de actualizare nu este asa de mare cand se utilizeaza blocarea doar la salvare fata de frecventa cazurilor in care pe baza de date nu se poate opera din cauza inregistrarilor blocate.

O aplicatie bine facuta ar trebui sa fie independenta de backend-ul utilizat, fie tabele vfp, fie server sql.
 L.E.: Voiam doar sa scot in evidenta faptul ca o baza de date utilizata shared, cum este un server sql, exclude prin constructie actualizarea fara tranzactii.



 Daniel Buduru wrote
Buffering:
2 – Sets pessimistic row buffering on.
3 – Sets optimistic row buffering on.
4 – Sets pessimistic table buffering on.
5 – Sets optimistic table buffering on

Blocarea pesimista penalizeaza performantele bazei de date. Sunt rare cazurile in care se justifica.
O inregistrare blocata afecteaza nu numai actualizarea ei, ci toate comenzile care opereaza la nivelul tabelei, cum ar fi sum, count,  etc. In acest caz, ceilalti utilizatori trebuie sa astepte eliberarea lock-ului inainte de a obtine informatiile cerute din baza de date. Si daca utilizatorul intra in editare, apoi in pauza de masa ....
Frecventa confilctelor de actualizare nu este asa de mare cand se utilizeaza blocarea doar la salvare fata de frecventa cazurilor in care pe baza de date nu se poate opera din cauza inregistrarilor blocate.

O aplicatie bine facuta ar trebui sa fie independenta de backend-ul utilizat, fie tabele vfp, fie server sql.
 L.E.: Voiam doar sa scot in evidenta faptul ca o baza de date utilizata shared, cum este un server sql, exclude prin constructie actualizarea fara tranzactii.



Nu vreau sa te cotrazic, stiu ca blocarea unei inregistrari afecteaza performantele, dar nu inteleg de ce zici ca afecteaza toate comenzile la nivelul tabelei. Ma refer la  Buffering 5 si la blocare inainte de modificare cu Rlock().  Vechile mele programe din FPD au fost construite pe aceasta logica ( bineneteles fara buffering ) si daca blocam inregistrarile unui document, ceilalti puteau sa foloseasca majoritatea comenzilor pe tabela respectiva, daca nu se solicita modificarea inregistrarilor blocate. Se putea vizualiza documentul blocat iar la incercarea de modificare se afisa un mesaj de avertisment. In rest se puteau adauga sau modifca alte documente. Intradevar ca daca cineva doarea sa faca o operatie care solicita blocarea intregului fisier pt scurt timp si exista un document in modificare si persoana respectiva era plecata de la calculator, cel care dorea sa faca operatia respectiva, incepea sa dea telefoane si sa faca investigatii. Dar deja lumea stia regulile
Acum caut o solutie pt a evita blocarea. Pt modificari la nivel de inregistrare ( in cazul nomenclatorelor ) problema confilictelor am rezolvat-o folosind cursoradapter asfel incat daca se modifica  campuri diferite ale aceleiasi inregistrari nu apare nici un conflict. In cazul in care se modifca acelasi camp, ultimul care salveaza poate vedea modificarea si are posibilitatea sa suprascrie sau sa renunte. Pentru documente cu mai multe pozitii tratarea conflictului este mult mai complicata. Solutia cu afisatul informatiilor modifcate si decizia userului de a pastra sau nu modifcarile lui nu prea tine. Sunt cazuri, cei drept rare, cand ambele modificari trebuie pastrate. Un simplu exemplu ar fi o factura netiparita la care facturistul modifica cantitatile deoarece s-a constatat ca nu sunt pe stoc iar in acelasi timp un sef  insereaza un comentariu deplasand primele pozitii in jos cu cateva randuri. Normal ca ambele modifcari trebuie sa ramana, dar seful va forta salvarea documentului pierzandu-se asfel modifcarile facute de operator. Corect ar fi ca modifcarile sa se interclaseze dar asta este destul de greu de realizat pt un document la care inserarea sau stergerea unei pozitii schimba tot contextul.



 1/30/2012 6:18:37 AM
User is offlinealemao
344 posts
3rd


Re: Ma roade ceva ...
 (N/A)
Nu vreau sa te cotrazic, stiu ca blocarea unei inregistrari afecteaza performantele, dar nu inteleg de ce zici ca afecteaza toate comenzile la nivelul tabelei. Ma refer la  Buffering 5 si la blocare inainte de modificare cu Rlock().  Vechile mele programe din FPD au fost construite pe aceasta logica ( bineneteles fara buffering ) si daca blocam inregistrarile unui document, ceilalti puteau sa foloseasca majoritatea comenzilor pe tabela respectiva, daca nu se solicita modificarea inregistrarilor blocate. Se putea vizualiza documentul blocat iar la incercarea de modificare se afisa un mesaj de avertisment. In rest se puteau adauga sau modifca alte documente. Intradevar ca daca cineva doarea sa faca o operatie care solicita blocarea intregului fisier pt scurt timp si exista un document in modificare si persoana respectiva era plecata de la calculator, cel care dorea sa faca operatia respectiva, incepea sa dea telefoane si sa faca investigatii. Dar deja lumea stia regulile
Acum caut o solutie pt a evita blocarea. Pt modificari la nivel de inregistrare ( in cazul nomenclatorelor ) problema confilictelor am rezolvat-o folosind cursoradapter asfel incat daca se modifica  campuri diferite ale aceleiasi inregistrari nu apare nici un conflict. In cazul in care se modifca acelasi camp, ultimul care salveaza poate vedea modificarea si are posibilitatea sa suprascrie sau sa renunte. Pentru documente cu mai multe pozitii tratarea conflictului este mult mai complicata. Solutia cu afisatul informatiilor modifcate si decizia userului de a pastra sau nu modifcarile lui nu prea tine. Sunt cazuri, cei drept rare, cand ambele modificari trebuie pastrate. Un simplu exemplu ar fi o factura netiparita la care facturistul modifica cantitatile deoarece s-a constatat ca nu sunt pe stoc iar in acelasi timp un sef  insereaza un comentariu deplasand primele pozitii in jos cu cateva randuri. Normal ca ambele modifcari trebuie sa ramana, dar seful va forta salvarea documentului pierzandu-se asfel modifcarile facute de operator. Corect ar fi ca modifcarile sa se interclaseze dar asta este destul de greu de realizat pt un document la care inserarea sau stergerea unei pozitii schimba tot contextul.



[/QUOTE]

Si eu m-am lovit de o problema asemanatoare acum. Ma gandesc ca in cazul unui conflict de acest gen sa-l scot automat din procesul de editare pe user-ul care incearca sa aplice o modificare asupra unei inregistrari care intre timp a fost modificata. Chiar daca ma v-a injura, macar v-a trebui sa verifice ceea ce s-a modificat. Da, desigur e si varianta afisarii modificarilor, insa, din experienta am vazut ca userii au tendinta de a aplica modificarile lor orice ar fi, chiar si in cazul in care userul anterioar facut exact aceleasi modificari (a se vedea adresa unui client).
 1/30/2012 10:22:08 AM
User is offlineEugen Gliga
2092 posts
1st




Re: Ma roade ceva ...
 (N/A)
 
Si eu m-am lovit de o problema asemanatoare acum. Ma gandesc ca in cazul unui conflict de acest gen sa-l scot automat din procesul de editare pe user-ul care incearca sa aplice o modificare asupra unei inregistrari care intre timp a fost modificata. Chiar daca ma v-a injura, macar v-a trebui sa verifice ceea ce s-a modificat. Da, desigur e si varianta afisarii modificarilor, insa, din experienta am vazut ca userii au tendinta de a aplica modificarile lor orice ar fi, chiar si in cazul in care userul anterioar facut exact aceleasi modificari (a se vedea adresa unui client).

Ai dreptate. Userul nu are rabdare sa verifice ce s-a modificat si va aplica modificarile lui. Ma gandesc, ca pt a evita blocarea s-ar putea introduce un camp logic cu semnificatie document in modificare, camp ce va fi setat de primul care incepe editarea si scos la sfarsitul editarii. Problema este ca acest camp trebuie comis si in caz de pana de curent sau de retea, documentul va ramane vesnic in editare.


 1/30/2012 11:22:30 AM
User is offlineDaniel Buduru
3513 posts
1st




Re: Ma roade ceva ...
 (N/A)
In toate cazurile e vorba de modalitatea aleasa pentru rezolvarea conflictelor.
Intr-o aplicatie bine structurata, conflictele de actualizare apar rar.
Daca aplicatia permite permite utilizatorior sa modifice tot ce vor, cand vor, oricand vor, si care nu au nici un fel de responsabilitate asupra datelor introduse, aste e.
In acest caz, blocarea pesimista a inregistrarilor poate fi solutia pefecta. Nu este insa solutia preferata de majoritatea dezvoltatorilor de aplicati.

Vfp nu va mai cunoaste vreo evolutie. Mai poate fi inca utilizat, dar partea cea mai slaba din vfp este baza lui de date, care nu a fost conceputa pe vremea cand multitasking si multiuser erau concepte inca neinventate ... VFP mai poate trai doar cu un server sql in backend - si nu ma refer aici la aplicatiile monouser.
Aplicatiile care se dezvolta acum in VFP ar trebui sa poata functiona astfel, si asta implica utilizarea unor tehnici de programare care pot fi utilizate si cu un server in backend.


Daniel Buduru
 1/30/2012 12:02:10 PM
User is offlineEugen Gliga
2092 posts
1st




Re: Ma roade ceva ...
 (N/A)
Ai dreptate, dar realitatea e urmatorea: Aplicatiile existente sunt functionale si trebuie intretinute pt ca ele aduc venit deocamdata. Tinand cont ca intretinerea lor ocupa cam jumatate din timpul disponibil, iar migrarea la o platforma client-server cu care nici nu esti acomodat ar lua suficient timp incat sa n-o poti finaliza intre doua actualizari la versiunea veche impuse de modifcarile legislative ( vezi d112, d394 sau d300), rezulta ca migrarea este un poces anevoios si de durata, cu toate ca ideal ar fi sa opresti orice interventie pe vechile programe si sa lucrezi doar pe noua aplicatie. Practic, beneficiarul nu prea da multi bani, daca-i spui ca-i inlocuiesti veche aplicatie cu una client-server, iar anumite aspecte din noul program chiar o sa-i displaca. Pana la urma munca o faci mai mult pt multumirea ta. Deocamdata inlocuind in forme, tabelele cu cursoradapter pe langa pregatirea pt client server incerc sa fac si anumite optimizari.



 1/30/2012 6:25:26 PM
User is offlinealemao
344 posts
3rd


Re: Ma roade ceva ...
 (N/A)
 Daniel Buduru wrote
In folderul FFC din vfp se gaseste biblioteca _app.vcx.
Obiectul _datasession din _app.vcx contine codul necesar pentru actualizarea inregistrarilor, fara buffering, cu buffering optimistic sau pesimitic, cu sau fara tranzactii, precum si codul pentru revert si altele.


Am aruncat un ochi aseara. Cred avand in vedere orle libere de care dispun coroborat cu felul in care a fost construita clasa, am banuiala, ba nu, am certitudinea ca va trece mult timp pana inteleg la nivel de detaliu biblioteca in cauza.
Dar, informatia este binevenita, si multumesc pentru ea.

 1/30/2012 6:34:46 PM
User is offlinealemao
344 posts
3rd


Re: Ma roade ceva ...
 (N/A) Modified By Grigore Dolghin  on 1/30/2012 9:33:47 PM)
 Eugen Gliga wrote
 
Ai dreptate. Userul nu are rabdare sa verifice ce s-a modificat si va aplica modificarile lui. Ma gandesc, ca pt a evita blocarea s-ar putea introduce un camp logic cu semnificatie document in modificare, camp ce va fi setat de primul care incepe editarea si scos la sfarsitul editarii. Problema este ca acest camp trebuie comis si in caz de pana de curent sau de retea, documentul va ramane vesnic in editare.



Stii ca m-am gandit la o asemenea rezolvare. Folosirea unui camp pe post de semafor ca sa zic asa. Evident ca ramane problema comutarii starii acestuia in cazul unei pene de curent sau de retea. Chiar am incercat implementarea dar nu a dat rezultatele scontate intrucat m-am prins tarziu ca acest camp trebuia comis (.T.) inainte de inceperea editarii, si comis din nou la valoarea initiala (.F.) indiferent daca userul modifica sau nu modificate ceva prin campurile inregistrarii.
 1/31/2012 7:47:55 AM
User is offlineDaniel Buduru
3513 posts
1st




Re: Ma roade ceva ...
 (N/A) Modified By Daniel Buduru  on 1/31/2012 7:51:14 AM)
Chiar discutati de situatii reale aici? Situatiile astea fie nu pot apare, fie, daca apar, nu au nici o rezolvare, indiferent daca intreaga baza de date este blocata pentru fiecare utilizator in parte sau daca se salveaza intodeauna ultima modificare.
Ce inseamna faptul ca mai multi utilizatori modifica aproape simultan aceeasi inregistrare dintr-un nomenclator? La momentul t1 userul x modifica o inregistrare in nomenclator, inregistrare pe care o refera in documentul pe care il intocmeste. La momentul t2, userul y modifica aceeasi inregistrare, cu valoarea de care are nevoie in dcoumentul sau. Modificarile se fac succesiv, deci nu e nici un fel de conflict de actualizare. In acest caz, ce valoare va arata documentul userului x? Valoarea introdusa in nomenclator de userul y, si nicidecum valoarea cu care userul x a intocmit documentul.
Daca este posibil sa apara o astfel de situatie, baza aia de date nu corespunde scopului, iar aplicatia functioneaza doar ca masina de scris. Daca o informatie de nomenclator este dinamica, nomenclatorul sigur are nevoie de versiunea inregistrarii si perioada de valabilitate a ei - de la data si ora pana la data si ora. In acest caz, orice modificare se face prin inserarea uneia noi si inchiderea valabilitatii versiunii precedente.
Daca o factura sau alt document asimilat poate fi modificata de mai multi utilizatori, altii decat cel care a intocmit documentul, atunci in firma aia e ceva putred, dar asta e treaba clientului. Dar daca tabela headerului facturii nu are un camp de comentarii, care sa fie tiparit in group header sau group footer, ci comentariile se scriu ca si pozitii din factura, atunci aplicatia trebuie regandita si rescrisa.

O lume intreaga lucreaza cu buffering optimistic, iar prin lumea intreaga inteleg chiar lumea intreaga. Sunt baze de date cu miliarde de inregistrari si milioane de accesari pe secunda, nu sute de mii de inregistrari la cativa useri, si sistemul nici nu crapa si nici userii nu-l abandoneaza.

Daca va puneti problema ce se face cu stocul sau cu alte informatii de acest gen, intrebati-va cum se rezolva rezervarea locurilor la o companie aeriana, sau a locurilor la un spectacol sau altele de acest gen, si daca cei care au proiectat sistemele alea s-au gandit sa blocheze inregistrarea in baza de date pana se hotaraste clientul ce loc vrea.

Exista solutii consacrate pentru toate problemele, solutii care s-au dovedit viabile in timp.

Daniel Buduru
 1/31/2012 8:43:44 AM
User is offlineDaniel Buduru
3513 posts
1st




Re: Ma roade ceva ...
 (N/A)
 alemao wrote
.....
Si eu m-am lovit de o problema asemanatoare acum. Ma gandesc ca in cazul unui conflict de acest gen sa-l scot automat din procesul de editare pe user-ul care incearca sa aplice o modificare asupra unei inregistrari care intre timp a fost modificata. Chiar daca ma v-a injura, macar v-a trebui sa verifice ceea ce s-a modificat. Da, desigur e si varianta afisarii modificarilor, insa, din experienta am vazut ca userii au tendinta de a aplica modificarile lor orice ar fi, chiar si in cazul in care userul anterioar facut exact aceleasi modificari (a se vedea adresa unui client).


Daca ai un conflict de actualizare poti compara camp cu camp valorile din buffare cu cele din tabela si sa i le prezinti userului pe cale care difera, pentru a decide ce pastreaza - valoarea din tabela sau valoare introdusa de el.
In cazul in care userul n-a modificat nimic intr-un camp care difera de cel din tabela - asta iti spune getfldstate() - inlocuiesti in buffer campul cu valoarea din tabela.
Daca sunt campuri modificate de catre user si modificate si in tabela, ii dai posibilitatea sa decida, pentru fiecare camp in parte, ce valoare pastreaza. Daca vrea sa pastreze valoarea din tabela, o inlocuiesti in buffer.
Apoi executi tableupdate cu optiunea Force - Tableupdate(1,.T., alias)

User id si timestamp in tabela servesc atat trasabilitatii, cat si responsabilizarii userului.


Daniel Buduru
 1/31/2012 8:44:20 AM
User is offlineGrigore Dolghin
3996 posts
www.class-software.ro
1st






Re: Ma roade ceva ...
 (N/A) Modified By Grigore Dolghin  on 1/31/2012 8:44:49 AM)
@Daniel: 100% agreed.

Grigore Dolghin
Visual FoxPro MVP 2006 - 2010
Class Software
My blog
 2/1/2012 1:37:56 AM
User is offlineEugen Gliga
2092 posts
1st




Re: Ma roade ceva ...
 (N/A)
Cred ca vorbim de lucruri diferite. Eu chiar vorbesc de situatii reale si caut o solutie de optimizarea a programului care momentan functioneaza dupa cum am zis. Sigur ca folosesc buffering otpimistic, dar blochez cu rlock headerul documentului pana cand userul salveaza modificarile. Poate la 99,99 la suta din firme situatia pe care o prezint nu exista, dar am avut ghinionul sa se intample la mine si poate nu are rost sa caut cea mai complexa rezolvare. Situatia este astfel: Este vorba de contracte foarte detaliate care contin anexe fiecare anexa putand avea de la zeci la sute de pozitii. Pozitiile din anexe se lanseaza in lucru pe baza de comenzi. Comenzile se finalizeaza la diverse intervale si se factureaza. O factura poate contine elemente din una sau mai multe anexe si poate avea de la cateva pozitii pana la cateva sute. Intocmirea unei facturi poate dura si o zi si decurge astfel. Directorul de vanzari zice operatorului sa factureze anexa x de la contractul y plus jumatate din anexa z. Factura trebuie sa contina pe tot parcursul ei ( nu in heder sau footer ) comentarii gen Anexa x poz. q-w din ctr.n, dupa care urmeaza pozitiile respective, iarasi comentariu si iarasi pozitii si explicatii. Dupa intocmire factura se verifica cu contractul de catre alta persoana de la tehnic care si el are dreptul sa faca corectii in facura. Urmeaza apoi incarcarea reperelor in masina unde seful productiei constata ca la anumite pozitii nu exista stocul respectiv si iarasi se fac modificari. In cursul zilei pana iese marfa pe poarta factura respectiva este in prim plan pe cel putin 4-5 calculatoare si fiecare este tentat sa dea modificare, unii doar pentru a parcurge mai usor pozitiile. Particularitatea facturilor este ca fiecare pozitie este identificata prin numarul ei de ordine. Deci daca inserezi sau stergi o linie toate liniile care urmeaza se modifca. Ce sa-i zic userului care a introdus o linie de separatie in mijlocul facturii si da salvare? Sa-i arat toate liniile vechii si noi in paralel si sa-i spun sa hotarasca? Asa daca permit doar unui singur user sa faca modifcari la un momenta dat, ei stau disciplinat la coada. Aici nu volumul de date e problema, dar probabilitatea de a accesa mai multi acceasi factura este 1 adica certitudine. La rezervat bilete este simplu, care da primul click face tranzactia si sigur nu e mare ingramadeala pe acelasi bilet. Doar la bursa probabil cred ca e ingramadeala mai mare dar sunt convins ca aia au programe bine gandite. La ANAF stie toata lumea ce se intampla in ultimele zile de depunere si ma gandesc ca nici aia nu sunt batuti in cap dar probail atata pot.
Da, am si firme care fac sute de facturi pe zi, dar odata facuta factura si listata este putin probabil s-o mai modifice cineva, modificarea fiind dealtfel blocata dupa tiparire.De intrat doi pe aceeasi factura nici nu se pune problema, dar fiecare firma are particularitatile ei. Am vazut si cum functioneaza in Danemarca o firma ca si cea descrisa mai sus. Totul e automatizat de la lansarea comenzii si pana la incarcarea in camion. No comment.


 2/1/2012 1:55:47 AM
User is offlineDaniel Buduru
3513 posts
1st




Re: Ma roade ceva ...
 (N/A) Modified By Daniel Buduru  on 2/1/2012 1:59:53 AM)
Buffering=4 - table buffering pesimistic.

Treaba cu biletul si cu click-ul nu e chiar asa, dar nu mai comentez.

Daniel Buduru
 2/1/2012 2:26:29 AM
User is offlineEugen Gliga
2092 posts
1st




Re: Ma roade ceva ...
 (N/A)
Am facut niste teste cu buffering=4 si au fost catastrofale. Cine face modificari trebuie sai aiba acces total la documentul. O inserare de linie inseamana adaugarea unei linii noi si deplasarea liniilor de sub pozitia curenta in jos cu o pozitie. Daca  altcineva  a blocat o linie nu mai pot face nimic.Deci tot mai bine este sa las doar un user sa faca modificari. Ma mai gandesc si la alte metode.
Referitor la blocarea manuala cu rlock doar a Headerului facturii am observat ca performantele nu sunt foarte tare afectate fata de situatia cand blochezi si pozitiile de Detail. Asta a fost una din optimizarile care a avut efecte vizibile. Daca calculezi ca un user poate bloca maxim o pozitie din tabela efectele nu sunt chiar catastrofale.








 2/1/2012 2:39:48 AM
User is offlineDaniel Buduru
3513 posts
1st




Re: Ma roade ceva ...
 (N/A) Modified By Daniel Buduru  on 2/1/2012 3:45:42 AM)
Cu buffering=4 nici un alt utilizator nu are acces la inregistrarile blocate.
Daca lucrezi direct pe tabela si nu intr-un view sau CA, atunci blocarea nu apare decat in momentul in care se modifica ceva in inregistrare, de aici posibilitatea ca diferiti utilizatori sa blocheze diferite inregistrari.

Chestia cu pozitia liniei nu o pot intelege. Intr-o baza de date fiecare linie are un identificator si eventual un camp pentru ordonare. Ordonarea lor se face in functie de un camp, nu de pozitia fizica in tabela.



Daniel Buduru
 2/1/2012 10:52:34 PM
User is offlineDaniel Buduru
3513 posts
1st




Re: Ma roade ceva ...
 (N/A)
 Eugen Gliga wrote
Am facut niste teste cu buffering=4 si au fost catastrofale. Cine face modificari trebuie sai aiba acces total la documentul. O inserare de linie inseamana adaugarea unei linii noi si deplasarea liniilor de sub pozitia curenta in jos cu o pozitie. Daca  altcineva  a blocat o linie nu mai pot face nimic.Deci tot mai bine este sa las doar un user sa faca modificari. Ma mai gandesc si la alte metode.
Referitor la blocarea manuala cu rlock doar a Headerului facturii am observat ca performantele nu sunt foarte tare afectate fata de situatia cand blochezi si pozitiile de Detail. Asta a fost una din optimizarile care a avut efecte vizibile. Daca calculezi ca un user poate bloca maxim o pozitie din tabela efectele nu sunt chiar catastrofale.


Ai dreptate. Am facut azi ceva teste pe dbf, n-am mai lucrat direct pe tabela de la vfp3 si nu mai lucrez cu dbf-uri de vreo 7 ani.
Singura modalitate in situatia expusa pentru a bloca documentul e blocarea explicita a headerului, asa cum faci, intrucat blocarea prin buffering pesimist se produce doar in momentul editarii efective a unei inregistrari, si nu in momentul intrarii in editarea documentului.

Solutia pe care am adoptat-o eu pentru o sutuatie similara - acelasi gen de factura  si cam acelasi mod de lucru al clientului - a fost cu o serie de documente preliminare, asimilate dispozitiei de livrare, intocmite si editate fiecare de persoanele/ compartimentele in cauza si asamblarea lor in factura abia cand nu mai sufera modificari.


Daniel Buduru
 2/2/2012 5:48:41 PM
User is offlineEugen Gliga
2092 posts
1st




Re: Ma roade ceva ...
 (N/A)
 Daniel Buduru wrote
Chestia cu pozitia liniei nu o pot intelege. Intr-o baza de date fiecare linie are un identificator si eventual un camp pentru ordonare. Ordonarea lor se face in functie de un camp, nu de pozitia fizica in tabela.


Pai ori n-am fost eu prea explicit ori am o abordare gresita a problemei. Sa zicem ca avem  un camp ca si identificator de ordine, care se incrementeaza odata cu adaugarea unei linii noi. In momentul in care vrem sa inseram o linie pe prima pozitie, adaugam o linie si ii dam identificatorul 1, dupa care trebui sa incrementam identificatorul fiecarei linii aflate dupa linia curenta. Rezulta modificarea a cel putin unui camp din fiecare linie. Asta in cazul in care folosim un index pt a afisa liniile in ordine. Eu prefer sa nu folosesc indexarea si deplasez toate liniile in jos pt a face un loc liber. Odata ce ai modificat ceva din fiecare linie iar numarul de linii este de ordinul sutelor nu prea ar fi indicat sa-i afisezi userului toate modificarile si sa-l pui sa decida.
Probabil ca exista si alte abordari dar lucurile se complica si mai mult.


 2/2/2012 7:06:44 PM
User is offlineDaniel Buduru
3513 posts
1st




Re: Ma roade ceva ...
 (N/A)
Nu am inteles eu bine.
Am avut o astfel de problema la o aplicatie in care trebuiau ordonate intrari care nu se faceau in ordine cronologica. Am rezolvat cu pozitia de tip double, in speta cu zecimale, ceea ce a permis ordonarea corecta oricate inserari s-ar fi facut intre doua pozitii. Intrucat tineam row version, am ales o solutie care sa nu necesite editarea tuturor inregistrarilor, ci numai a celei nou introduse.
Alocarea numarului de pozitie se face automat, userul indicand doar pozitia after sau before fata de o alta linie.




Daniel Buduru
 2/3/2012 12:39:03 AM
User is offlineEugen Gliga
2092 posts
1st




Re: Ma roade ceva ...
 (N/A)
M-am gandit si eu la varianta asta, dar atunci ca sa pot afisa si numarul de ordine absolut ar trebui sa mai tin un cursor cu corespondenta dintre double si numarul de ordine.
Ma gandesc ca indexul pozitiei inserate se calculeaza ca medie aritmetica a indecsilor pozitiilor intre care se face inserarea.




 2/3/2012 1:19:31 AM
User is offlineDaniel Buduru
3513 posts
1st




Re: Ma roade ceva ...
 (N/A)
 Eugen Gliga wrote
M-am gandit si eu la varianta asta, dar atunci ca sa pot afisa si numarul de ordine absolut ar trebui sa mai tin un cursor cu corespondenta dintre double si numarul de ordine.
...

Lucrand doar cu comenzi sql, eu aloc intotdeauna pozitia direct in cursor, si nu am in tabela un camp pozitie care sa fie tiparit.

Printre cerintele pe care le-am avut la acea aplicatie a fost si aceea ca factura sa respecte, intr-o oarecare masura, comanda client. Pe aceasta erau referintele articol care trebuiau sa se regaseasca pe factura. Am inceput prin a prelua comanda apoi pe baza ei am generat celelalte documente, modificarile fiind, in general, la cantitati, iar cantitate 0 inseamna ca pozitia nu se livreaza si nu mai intra pe factura.

 Eugen Gliga wrote
...
Ma gandesc ca indexul pozitiei inserate se calculeaza ca medie aritmetica a indecsilor pozitiilor intre care se face inserarea.

Cam asa, doar ca se rotunjeste la valoarea cea mai mare care asigura pozitia corecta, si nu cu toate zecimalele rezultate din calcul, astfel incat sa nu consume inutil spatiul de adrese.

Daniel Buduru
  Visual FoxPro  Baze de date, tabele, view-uri si indecsi  Ma roade ceva ....

Search  Forum Home         

 Google Ads Minimize

    

Copyright 2002-2013 Profox   Terms Of Use  Privacy Statement