Referat MANIPULAREA BAZELOR DE DATE

label Referate autorenew 29 Sep 2025, 16:56 history_edu virgil
Manipularea bazelor de date utilizand clase specializate MFC Open Database Conectivity (ODBC) si MFC ODBC reprezinta o interfata de programare a aplicatiilor (API) pentru accesul la bazele de date. Principala caracteristica a ODBC este interoperabilitatea abilitatea de a accesa diferite sisteme de gestiune a bazelor de date utiliznd acelasi cod sursa. Limbajul utilizat de ODBC pentru accesarea bazelor de date este SQL. MFC ncapsuleaza functionalitatea ODBC prin intermediul a doua clase: CDatabase si CRecordset (pentru utilizarea acestor clase este necesara includerea in proiect a fisierului ). Orice program care utilizeaza MFC si baze de date ODBC va folosi cel putin o instanta a clasei CDatabase si cel putin o instanta a clasei CRecordset. O sursa de date (data source) reprezinta o entitate care contine si furnizeaza date. Formatul unei surse de date este dat de Sistemul de Gestiune a Bazelor de Date (SGBD) care a creat sursa de date. Exemple de astfel de sisteme sunt: Microsoft SQL Server, Microsoft Access, Borland dBASE sau xBASE. O sursa de date este compusa din trei parti: - multime particulara de date, - un set de informatii necesare pentru a accesa datele, - locatia unde sunt stocate datele. Locatia de stocare a datelor este descrisa prin intermediul unui Data Source Name (DSN). Multimea tuturor DSN-urilor definite ntr-un sistem sunt retinute ntr-un fisier special, numit ODBC.ini (n cazul sistemelor de operare din familia Windows pe 16 biti) sau n registrii sistem (n cazul sistemelor de operare pe 32 de biti). Crearea unui DSN se poate realiza att prin apelarea functiei ODBC API SQLConfigDataSource(...) ct si prin intermediul intrumentului Control Panel.Clasa CDatabase Clasa CDatabase permite conectarea la o baza de date prin intermediul unui DSN. Cele mai importante functii implementate n clasa CDatabase sunt Open(), OpenEx(), Close() si ExecuteSQL().virtual BOOL Open( LPCTSTR lpszDSN, BOOL bExclusive = FALSE, BOOL bReadOnly = FALSE, LPCTSTR lpszConnect = ODBC;, BOOL bUseCursorLib = TRUE ); Rezultatul returnat de functia Open() specifica daca s-a reusit sau nu conectarea la baza de date dorita. Parametrii specifica respectiv: numele sursei de date (lpszDSN), tipul de conectare la baza de date: n mod exclusiv sau nu (bExclusive) si n mod citire/scriere sau doar citire (bReadOnly), textul de conectare la baza de date ce contine identificatorul si parola de utilizare a bazei de date precedate obligatoriu de textul "ODBC;" (lpszConnect), ncarcarea bibliotecii de cursoare ODBC (bUseCursorLib). n cazul n care anumiti parametrii nu contin suficiente informatii pentru deschiderea unei conexiuni (lipseste spre exemplu parola de conectare), la apelul functiei Open() este afisata automat o cutie de dialog care va solicita aceste informatii.virtual BOOL OpenEx( LPCTSTR lpszConnectString, DWORD dwOptions = 0 ); Rezultatul returnat de functia OpenEx() specifica de asemenea succesul sau insuccesul conectarii la baza de date. Parametrul lpszConnectString contine stringul de conectare ODBC care include numele sursei de date, identificatorul si parola utilizator (sub forma "DSN=;UID=;PWD="). Parametrul dwOptions contine o combinatie a mai multor constante numerice definite la nivelul clasei CDatabase: openExclusive (acces exclusiv la baza de date), openReadOnly (sursa de date nu poate fi modificata), userCursorLib (ncarcarea bibliotecii de cursoare ODBC), noOdbcDialog (nu permite deschidere cutiei de dialog n cazul n care parametrul lpszConnectString nu contine informatii suficiente de deschidere a unei conexiuni), forceOdbcDialog (forteaza deschiderea cutiei de dialog de conectare ODBC indiferent de continutul parametrului lpszConnectString).virtual void Close( ); nchide conexiunea la o baza de date. nainte de apelarea acestei functii trebuiesc nchise toate obiectele de tip CRecordset atasate bazei de date respective.void ExecuteSQL( LPCSTR lpszSQL ); Parametrul lpszSQL contine o comanda SQL valida care, n urma apelului functiei, va fi executata asupra bazei de date pentru care s-a deschis conexiunea. Deoarece functia nu returneaza nregistrari sau alte valori, este inutila executarea unei comenzi SELECT SQL, pentru aceasta fiind utilizata clasa CRecordset.Exemplu: Sa presupunem ca baza de date asupra careia vom opera este o baza de date Access, salvata pe disc sub numele de Ex.mdb. Aceasta baza de date va contine o tabela numita Studenti, cu trei cmpuri: ID (Numeric, integer), Nume (text(50)), Medie (Numeric, double), DataNasterii (Date/Time). Urmatorul fragment de cod exemplifica utilizarea clasei CDatabase pentru conectare si operarea asupra bazei de date Ex.mdb (vom presupune ca exista deja creat un DSN pentru aceasta baza de date, cu numele Exemplu):. . . . . . . . . CDatabase aDatabase;if( aDatabase.OpenEx("DSN=Exemplu") ) //deschide o conexiune la baza de date {aDatabase.ExecuteSQL("DELETE * FROM Studenti WHERE Medie < 5"); //sterge nregistrarile a caror medie este < 5aDatabase.ExecuteSQL("INSERT INTO Studenti (ID, Nume, Medie, DataNasterii) VALUES (10, 'Popescu Ioan', 9.00, 11/11/1980)"); //adaugare nregistrare noua aDatabase.Close(); //nchidere conexiune}. . . . . . . . . Clasa CRecordset Clasa CRecordset este utilizata n manipularea unei multimi de nregistrari apartinnd unei anumite surse de date. Aceasta multime de nregistrari poate avea un caracter static sau dinamic (n functie de vizibilitatea modificarilor efectuate asupra nregistrarilor de catre alti utilizatori ai bazei de date). Clasa CRecordset ofera functii de obtinere a acestor nregistrari (Open(), Close()), navigare prin multimea de nregistrari (MoveFirst(), MoveLast(), MoveNext(), MovePrev(), Move(), Set Absolute Position(), SetBookmark(), GetBookmark()), interogarea starii multimii de nregistrari (GetStatus(), IsOpen(), IsBOF(), IsEOF(), IsDeleted() etc), actualizarea nregistrarilor (AddNew(), Delete(), Edit(), Update(), CancelUpdate()) etc. Obtinerea unei multimi particulare de nregistrari dintr-o baza de date se realizeaza prin atasarea unui obiect de tip CRecordset unei baze de date si apelarea functiei Open() a acestuia care are urmatorul prototip:virtual BOOL Open( UINT nOpenType=AFX_DB_USE_DEFAULT_TYPE, LPCTSTR lpszSQL=NULL, DWORD dwOptions=none ); Rezultatul returnat de functia Open() specifica daca s-a reusit sau nu obtine multimea de nregistrari dorita. Putem privi multimea nregistrarilor obtinute n urma deschiderii unui obiect de tip CRecordset ca fiind memorata sub forma unei liste dublu nlantuite. Functiile de actualizare a nregistrarilor, ca Delete(), Edit(), Update() etc, actioneaza asupra unei singure nregistrari din multimea de nregistrari; aceasta nregistrare poarta numele de nregistrare curenta. Imediat dupa apelarea functiei Open(), prima nregistrare din lista de nregistrari obtinuta devine nregistrare curenta. Navigarea n lista de nregistrari se realizeaza prin intermediul functiilor MoveFirst() prima nregistrare devine nregistrare curenta, MoveLast() ultima nregistrare devine nregistrare curenta, MoveNext() activeaza urmatoarea nregistrare n lista, MovePrev() activeaza precedenta nregistrare din lista. Atingerea capetelor listei de nregistrari se poate determina apelnd functiile IsEOF() (sfrsitul listei) si IsBOF() (nceputul listei). Daca n urma deschiderii unui obiect de tip CRecordset, acesta nu are nici o nregistrare atasata, atunci att IsEOF() ct si IsBOF() vor returna valoarea TRUE. Functionalitatea unei multimi de nregistrari poate apartine uneia dintre urmatoarele categorii de comportament: - forwardOnly: navigarea n lista de nregistrari se poate realiza ntr-un singur sens (de la prima nregistrare spre ultima), iar nregistrarile nu pot fi modificate; - dynamic: este caracterizata de navigare bidirectionala si asigura vizibilitatea modificarilor efectuate de catre alti utilizatori asupra nregistrarilor (modificari de valori, ordonari etc); - snapshot: permite navigare bidirectionala. Modificarile realizate de alti utilizatori nu sunt vizibile dect dupa o evenuala re-deschidere a obiectului CRecordset; - dynaset: permite navigare bidirectionala si vizualizarea modificarilor realizate de alti utilizatori. Ordonarea este stabilita nsa n momentul deschiderii. De asemenea stergeri sau adaugari de noi nregistrari operate de alti utilizatori nu sunt vizibile dect dupa o eventuala re-deschidere. Primul parametru al functiei Open() specifica categoria de comportament dorita, si poate lua una dintre urmatoarele valori: CRecordset::forwardOnly, CRecordset::dynamic, CRecordset::shapshot sau CRecordset::dynaset. Daca se foloseste constanta AFX_DB_USE_DEFAULT_TYPE valoarea comportamentul implicit este snapshot, iar urmatorii parametrii nu sunt necesari, deoarece vor fi obtinuti prin apeluri ale functiilor GetDefaultConnect() si GetDefaultSQL(). Cel de-al doilea parametru al functiei Open(), lpszSQL, reprezinta un sir de caractere ce contine numele unei tabele, apelul unei interogari sau o fraza SELECT SQL valida. Cel de-al treilea parametru permite detalierea specificarii comportamentului multimii de nregistrari (v. MSDN). Functia Close() are ca efect eliberarea memoriei utilizate de obiectul CRecordset pentru gestionarea unei multime de nregistrari. Prototipul sau este:virtual void Close( ); Dupa apelarea functiei Close(), obiectul CRecordset poate fi redeschis utiliznd functia Open(). Daca valorile parametrilor transmisi functiei Open() nu se modifica, n locul a doua apeluri successive Close()-Open() se recomanda utilizarea functiei Requery() care va avea acelasi efect. n general clasa CRecordset va fi rareori utilizata prin instantiere directa ntr-o aplicatie. Se recomanda definirea de clase proprii, descendente ale clasei CRecordset, specializate pe tipul nregistrarilor ce urmeaza a fi manipulate. Aceste clase vor avea variabile membru ce corespund fiecarui cmp ce caracterizeaza multimea de nregistrari. Astfel, pentru gestionarea tabelei Studenti (v. exemplul anterior), vom putea defini o clasa CStudentiRecordset care va avea urmatoarea structura: Functiile GetDefaultConnect() si GetDefaultSQL() sunt rescrise pentru a simplifica operatia de deschidere a unui astfel de recordset. Functia DoFieldExchange() permite transferul valorilor variabilele membru n cmpurile din baza de date asociate. Procesul este foarte asemanator cu transferul de date ntre variabile membru si controale n cadrul claselor de implementare a cutiilor de dialog (v. Curs 4). De asemenea, Class Wizard ofera suport n crearea de noi clase descendente din CRecordset, genernd cod sursa care n marea majoritate a cazurilor nu necesita modificare pe parcursul dezvoltarii aplicatiei. n cele ce urmeaza sunt prezentate fragmente de cod sursa generate de catre instrumentul Class Wizard pentru implementarea clasei CStudentiRecordset. Fisierul StudentiRecordset.h: . . . // Field/Param Data//{{AFX_FIELD(CStudentiRecordset, CRecordset)longm_ID;CStringm_Numedoublem_Medie;CTimem_DataNasterii;//}}AFX_FIELD // Overrides// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CStudentiRecordset)public:virtual CString GetDefaultConnect(); // Default connection stringvirtual CString GetDefaultSQL(); // Default SQL for Recordsetvirtual void DoFieldExchange(CFieldExchange* pFX); // RFX support//}}AFX_VIRTUAL. . . Fisierul StudentiRecordset.cpp:. . .CStudentiRecordset::CStudentiRecordset(CDatabase* pdb): CRecordset(pdb){//{{AFX_FIELD_INIT(CStudentiRecordset)m_ID = 0;m_Nume = _T("");m_Medie = 0.0;m_nFields = 4;//}}AFX_FIELD_INITm_nDefaultType = snapshot;} CString CStudentiRecordset::GetDefaultConnect(){return _T("ODBC;DSN=Exemplu");} CString CStudentiRecordset::GetDefaultSQL(){return _T("[Studenti]");}void CStudentiRecordset::DoFieldExchange(CFieldExchange* pFX){//{{AFX_FIELD_MAP(CStudentiRecordset)pFX->SetFieldType(CFieldExchange::outputColumn);RFX_Long(pFX, _T("[ID]"), m_ID);RFX_Text(pFX, _T("[Nume]"), m_Nume);RFX_Double(pFX, _T("[Medie]"), m_Medie);RFX_Date(pFX, _T("[DataNasterii]"), m_DataNasterii);//}}AFX_FIELD_MAP}. . . De remarcat functiile cu prefixul RFX_ (Recordset Field eXchange). Acestea realizeaza practic transferul datelor ntre anumite cmpuri din baza de date si variabile C++. Funtia DoFieldExchange() este apelata ori de cte ori este se schimba nregistrarea curenta (transfer cmpuri -> variabile membru) sau cnd este apelata functia Update() (transfer variabile membru -> cmpuri). De fiecare data cnd se doreste adaugarea unei noi nregistrari n baza de date se va apela functia AddNew() (n acest moment variabilele membru asociate cmpurilor vor avea valorile implicite specificate si n constructor), se vor initializa variabilele dorite, dupa care se va apela Update(). Orice alta actiune de navigare (ex. MoveNext()) fara apelarea functiei Update() n prealabil are ca efect anularea introducerii noii nregistrari. Modificarea unei nregistrari se realizeaza n mod analog, apelnd functia Edit(). Dupa modificarea valorilor unor variabile membru, apelul functiei Update() are ca afect actualizarea nregistrarii curente n baza de date.