Sunteți pe pagina 1din 24

Medii și Tehnologii de Programare – curs

7. Baze de date în Visual C# .NET

În industrie, majoritatea aplicațiilor nu mai pot fi dezvoltate fără a interacționa cu o bază de


date. Bazele de date servesc stocării datelor astfel încât acestea să poată fi extrase ulterior
(prin interogări SQL sau prin aplicații de baze de date).
În Visual Studio .NET controalele și componentele puse la dispoziție pentru lucrul cu baze de
date permit utilizatorului să interacționeze cu aplicația, aceasta afișând date către utilizator,
iar mediul de programare controlând aplicația. Controalele și componentele specializate aduc
datele din baza de date către aplicație, permițând acesteia să trimită înapoi date către baza de
date.
Programarea cu baze de date este un subiect vast, cu anevoie de acoperit într-un singur
capitol. Acest capitol își propune prezentarea modului de lucru cu bazele de date și descrierea
unor controale, componente și obiecte utile oferite de Visual C# pentru lucrul cu bazele de
date.

7.1. Conectarea automată la baza de date


Visual Studio .NET oferă controale și instrumente care fac ușoară conectarea la baza de date.
Pentru a construi un program simplu cu baze de date, vom crea un proiect nou de tip Windows
Forms Application. Apoi, din meniul Project, alegem comanda „Add New Data Source”, care va
afișa un dialog pentru configurarea conectării la baza de date, precum se poate observa în
Figura 7.1.

Figura 7.1. Dialogul pentru configurarea sursei datelor

Visual Studio .NET permite utilizarea bazelor de date, a serviciilor web și a obiectelor în
aplicația noastră. Ceea ce vom selecta noi în continuare, pentru a prelua datele dintr-o bază de

136
Baze de date în Visual C# .NET

date, este opțiunea „Database”, după care vom trece la pasul următor, alegerea unui model de
bază de date, precum se poate observa în dialogul din Figura 7.2.

Figura 7.2. Alegerea unui model de bază de date.

Dacă în cadrul unor proiecte anterioare am creat conexiuni la baze de date, putem să le
selectăm din lista derulantă (Figura 7.3). Dacă dorim să creăm o noua conexiune, vom apăsa
butonul „New Connection”, caz în care va apărea dialogul din Figura 7.4.

Figura 7.3. Alegerea conexiunii la o bază de date

137
Medii și Tehnologii de Programare – curs

Figura 7.4. Fereastra dialog pentru crearea unei noi conexiuni la baza de date.

Dacă baza noastră de date este în alt format decât cel implicit (în acest exemplu, Microsoft
Access Database), vom apăsa butonul „Change”, caz în care va apărea o fereastră de dialog
(Figura 7.5) din care putem selecta unul din tipurile de baze de date existente, cum ar fi
Microsoft Access, o sursă ODBC, SQL Server sau Oracle.

Figura 7.5. Dialogul pentru selectarea tipului de bază de date.

După ce am selectat tipul de bază de date dorit, ne vom întoarce la fereastra Add Connection.
Conținutul acestei ferestre va diferi în funcție de tipul de bază de date selectat.
Pentru baza de date Microsoft Access trebuie să introducem numele fișierului sau să apăsăm
butonul „Browse” (vezi Figura 7.4) pentru a găsi și selecta fișierul de bază de date. Dacă este
necesar, vom introduce suplimentar numele de utilizator și parola pentru accesul la baza de
date.
La întoarcerea în fereastra Data Source Configuration Wizard, selectăm noua conexiune, așa
cum este prezentat în Figura 7.6. Tot aici putem vizualiza șirul de conectare la baza noastră de
date.

138
Baze de date în Visual C# .NET

Figura 7.6. Conexiunea la baza de date și vizualizarea șirului de conectare

La pasul următor, vom fi informați că baza noastră de date este un fișier local și vom fi întrebați
dacă vrem să o adăugăm la proiectul nostru (Figura 7.7). Dacă selectăm „Yes”, baza de date va
fi inclusă în proiect și va apărea în fereastra Project Explorer. Dacă dorim să distribuim baza
de date împreună cu aplicația noastră, este mai convenabil să gestionăm baza de date și codul
Visual C# împreună. Totuși, în acest caz există un inconvenient (o setare implicită): ori de câte
ori proiectul va fi compilat, baza de date va fi copiată din locația originală în directorul
aplicației, suprascriind-o pe cea existentă și existând astfel riscul de a pierde ultimele date
adăugate. Acest neajuns se poate remedia prin setarea, din Solution Explorer, pentru fișierul
de bază de date, a proprietății „Copy to Output Directory” la valoarea Copy if newer (Figura
7.8).

Figura 7.7. Dialogul care apare la selectarea unei baze de date dintr-un fișier local

Figura 7.8. Setarea corespunzătoare a proprietăților bazei de date

139
Medii și Tehnologii de Programare – curs

În continuare vom fi întrebați dacă dorim să salvăm informațiile despre conectare în fișierul
de configurare al aplicației noastre. Dacă lăsăm selectată această opțiune atunci aceste
informații vor fi adăugate în fișierul app.config. (Figura 7.9)

Figura 7.9. Salvarea șirului de conectare la baza de date

Mai jos este prezentat conținutul fișierului app.config unde sunt stocate informațiile despre
conectarea la baza de date.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
</configSections>
<connectionStrings>
<add name="WindowsFormsApplication1.Properties.Settings.CatalogConnectionString"
connectionString="Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Catalog.accdb"
providerName="System.Data.OleDb" />
</connectionStrings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>

Fereastra următoare conține informații despre obiectele din baza de date. În acest exemplu,
baza de date conține două tabele: Studenti și Note. Putem desfășura informațiile despre tabele,
afișate arborescent, pentru a vedea ce câmpuri conțin și, eventual, pentru a selecta numai o
parte dintre acestea (vezi Figura 7.10).

140
Baze de date în Visual C# .NET

Figura 7.10. Selectarea tabelelor și a câmpurilor din baza de date

După încheierea wizard-ului (comanda „Finish”) la aplicația noastră vor fi adăugate câteva
obiecte. Fereastra Solution Explorer (Figura 7.11) afișează două obiecte: baza de date
Catalog.accdb și fișierul CatalogDataSet.xsd care descrie sursa de date.

Figura 7.11. Obiectele adăugate în fereastra Solution Explorer

Dacă dam dublu click pe fișierul *.xsd, Visual C# va deschide un editor (Figura 7.12) care va
afișa tabele împreună cu câmpurile lor și relațiile definite între tabele (dacă există așa ceva).

141
Medii și Tehnologii de Programare – curs

Figura 7.12. Tabele definite și relația dintre ele.

Linia trasată între cele 2 obiecte, având la un capăt o pictogramă cheie, iar la celălalt simbolul
“infinit”, indică faptul ca relația dintre tabele este de tip one-to-many. În acest exemplu, câmpul
IDStudent din tabelul Studenti împreună cu câmpul IDStudent din tabelul Note formează o
relație de tip foreign key. Aceasta înseamnă că fiecare valoare IDStudent din tabelul Note
trebuie să corespundă unei singure valori IDStudent din tabelul Studenti. Dacă se efectuează
dublu click pe link-ul de relaționare (sau click dreapta), editorul va afișa fereastra din Figura
7.13.

Figura 7.13. Detaliile privitoare la relația dintre tabelele Studenti și Note

În partea de jos a tabelelor afișate în Figura 7.12, se pot observa două obiecte de tip data
adapter care conțin etichetele “Fill, GetData()”. Aceste obiecte vor fi folosite mai târziu în
aplicație pentru a muta datele din/în baza de date.

142
Baze de date în Visual C# .NET

În plus, wizard-ul a adăugat în fereastra Data Sources un nou obiect DataSet (vezi Figura 7.14).
Dacă fereastra Data Sources nu este vizibilă, se poate selecta din meniul View –> Other
Windows –> Data Sources.
În Figura 7.14 este prezentat dataset-ul afișat sub formă arborescentă, fiind vizibile tabelele
și câmpurile acestora. Se poate observa că tabelul Note este listat sub tabelul Studenti,
deoarece există o relație părinte-copil între cele două.

Figura 7.14. Fereastra Data Sources.

Este nevoie de multe cuvinte și figuri pentru descrierea acestui proces, dar, utilizând wizard-
ul, această operațiune devine foarte rapidă. După ce am creat legătura la sursa de date putem
construi pentru aplicația noastră o interfață simplă fără nici un efort. Trebuie doar să tragem
pe formularul nostru cu drag–and–drop obiectele din fereastra Data Sources.
Dacă facem click pe unul dintre tabelele afișate în Data Sources apoi îl tragem cu drag-and-
drop peste un formular, Visual C# creează automat controalele BindingNavigator și
DataGridView, precum și alte componente utile pentru afișarea datelor din tabel (vezi Figura
7.15)

Figura 7.15. Afișarea datelor sub formă tabelară

În loc să afișăm tot tabelul pe formular, putem să tragem numai anumite câmpuri din tabel. În
acest caz, Visual C# adaugă controale pe formular pentru a reprezenta coloanele.
Dacă selectăm un tabel din fereastra Data Sources, va apărea un meniu drop down care ne
oferă posibilitatea de a alege stiluri diferite de afișare, așa cum se poate observa în Figura 7.16.
De exemplu, dacă setam stilul de afișare la Details și apoi tragem tabelul pe formularul noastru,
Visual C# va afișa datele din tabel utilizând o afișare detaliată a câmpurilor, precum se poate
vedea în Figura 7.17.

143
Medii și Tehnologii de Programare – curs

Figura 7.16. Meniul drop down obținut în urma efectuării click dreapta pe tabel

Figura 7.17. Afișare în stil Details a datelor din tabel

Similar, se poate schimba modul de afișare pentru orice câmp din tabelul nostru. Se selectează
câmpul din fereastra Data Sources, iar din meniul drop down care apare putem selecta
controlul în care să fie afișate pe formular datele din acel câmp (vezi Figura 7.18). Atunci când
trageți câmpul sau tabelul pe un formular pentru construirea interfeței aplicației, Visual C# va
utiliza acest tip de control pentru afișarea valorilor câmpului.

Figura 7.18. Asocierea unui câmp cu un control la afișarea în modul Details

7.2. Obiecte create automat


Atunci când un tabel sau un câmp (coloană) este tras prin drag-and-drop din fereastra Data
Sources pe o interfață, Visual C# face mai mult decât să plaseze un control DataGridView pe
interfață. El creează, de asemenea, o mulțime de alte controale și componente. Dintre acestea
cele mai importante sunt DataSet, TableAdapter, BindingSource și BindingNavigator (vezi
Figura 7.19)

144
Baze de date în Visual C# .NET

Figura 7.19. Visual C# folosește componentele DataSet, TableAdapter, TableAdapterManager, BindingSource și


BindingNavigator pentru a opera cu datele din baza de date.

Programul stochează datele într-un obiect de tip DataSet. Un obiect DataSet reprezintă o bază
de date. Acesta conține obiecte de tip DataTable, care reprezintă tabelele din baza de date.
Fiecare obiect DataTable conține obiecte DataRow, care reprezintă înregistrările din baza de
date, iar fiecare obiect DataRow conține obiecte DataColumn, care reprezintă câmpurile din
tabele.
Obiectele de tip TableAdapter sunt utilizate pentru comunicația dintre aplicație (mai precis,
un obiect DataSet) și o bază de date. Acestea oferă metode pentru efectuarea operațiilor
asupra bazei de date (cum ar fi selectare, inserare, modificare sau ștergere). Un TableAdapter
se conectează la o bază de date, execută interogări SQL sau proceduri stocate și poate returna
fie un tabel nou, populat cu datele returnate, fie un obiect DataTable existent, populat cu datele
returnate. Obiectele TableAdapter sunt utilizate de asemenea pentru a trimite date actualizate
de la aplicația curentă înapoi la baza de date.
TableAdapterManager reprezintă o componentă care oferă funcții de salvare a datelor în
tabele relaționate. TableAdapterManager utilizează relațiile de tip foreign-key, care
relaționează tabelele, pentru determinarea ordinii corecte de trimitere a comenzilor Insert,
Update sau Delete de la un DataSet către o bază de date fără încălcarea regulilor definite prin
intermediul foreign-key-urilor din baza da date.
Obiectul BindingSource încapsulează toate datele din DataSet și oferă funcții pentru controlul
acestora din cadrul programului. Aceste funcții efectuează acțiuni cum ar fi: mutarea datelor,
adăugarea sau ștergerea elementelor, etc.
BindingNavigator oferă o interfață grafică pentru ca utilizatorul să poată controla
BindingSource.
Figura 7.20 ilustrează legăturile dintre obiectele DataSet, TableAdapter, BindingSource și
BindingNavigator.

145
Medii și Tehnologii de Programare – curs

Figura 7.20. Legătura dintre obiecte DataSet, TableAdapter, BindingSource și BindingNavigator

Chiar și aceste obiecte, lucrând împreună, nu fac totul pentru ca informațiile să fie afișate de
program. Când creează aceste obiecte, Visual C# adaugă, de asemenea, la formularul nostru
codul prezentat mai jos. Event handler-ul Form1_Load() face ca TableAdapter-ul să copieze
toate datele din baza de date în DataSet, iar studentiBindingNavigatorSaveItem_Click() se
execută în momentul când utilizatorul face click pe comanda „Save” din BindingNavigator.
Această metodă face ca TableAdapter-ul să salveze orice modificare a tabelului Studenti în
baza de date.
private void studentiBindingNavigatorSaveItem_Click(object sender, EventArgs e)
{
this.Validate();
this.studentiBindingSource.EndEdit();
this.tableAdapterManager.UpdateAll(this.catalogDataSet);
}

private void Form1_Load(object sender, EventArgs e)


{
// TODO: This line of code loads data into the 'catalogDataSet.Studenti' table.
// You can move, or remove it, as needed.
this.studentiTableAdapter.Fill(this.catalogDataSet.Studenti);
}

Visual C# creează toate acestea automat, iar dacă rulăm programul vom vedea toate
informațiile din baza de date afișate, având posibilitatea de a le manipula. Aplicația obținută
nu este perfectă, în sensul că, printre altele, nu există nicio validare a datelor, lăsând
utilizatorul să închidă aplicația fără să salveze modificările făcute în baza de date. Este totuși
un început bun, pentru atât de puțin efort depus.

7.3. Alte obiecte pentru lucrul cu baze de date


Dacă dorim să creăm un program care să afișeze și să modifice datele din baza de date, cel
descris anterior este destul de bun. În acest caz, vom permite ca Visual Studio să implementeze
automat partea de conectare la baza de date, utilizatorul nefiind nevoit să aprofundeze
detaliile lucrului cu baze de date. De asemenea, putem crea propriile noastre obiecte DataSet,
TableAdapter, BindingSource și BindingNavigator pentru construirea propriilor aplicații
pentru lucrul cu baze de date.
Dacă este nevoie să manipulăm direct din cod datele din baza de date, nu are sens să creăm
toate aceste obiecte. Dacă, de exemplu dorim să modificăm o înregistrare, nu are sens să creăm
obiecte DataGridView, BindingNavigator și BindingSource.
Pentru cazuri ca acestea, Visual C# pune la dispoziție alte câteva tipuri de obiecte care pot fi
folosite pentru a interacționa cu baza de date. Aceste obiecte se împart în următoarele
categorii:

146
Baze de date în Visual C# .NET

• DataContainer: stochează datele, după ce acestea au fost încărcate din baza de date în
aplicație, similar DataSet-urilor. La aceste obiecte pot fi legate controale, pentru
afișarea automată a datelor și manipularea bazei de date.
• Connection: oferă informații care îi permit programului conectarea la o bază de date.
• DataAdapter: permit mutarea datelor între baza de date și containerul de date.
• Command: oferă instrucțiuni pentru manipularea datelor. Un obiect de tip Command
poate selecta, insera, modifica sau șterge date din baza de date. De asemenea, poate
executa proceduri stocate în baza de date.
Clasele de tip DataContainer și DataAdapter sunt generice și lucrează cu diferite tipuri de baze
de date, în timp ce obiectele de tip Connection și Command sunt specifice anumitor tipuri de
baze de date. De exemplu, obiectele de conectare OleDbConnection, SqlConnection,
OdbcConnection și OracleConnection pot lucra cu OLE DB (Object Linking and Embedding
DataBase), SQL Server – incluzând MSDE (MicroSoft Data Engine), ODBC (Open DataBase
Connectivity), respectiv baze de date Oracle.
Obiectele SQL Server și Oracle pot lucra doar cu baze de date care fac parte din același brand,
dar ele sunt mai complete și mai potrivite pentru baze de date SQL, respective Oracle.

7.4. O privire de ansamblu asupra datelor


O aplicație folosește trei obiecte de bază pentru a muta datele în/din baza da date: o
conexiune, un adaptor de date și un container de date cum ar fi DataSet. Obiectul de tip
Connection definește conexiunea la baza de date. Acesta conține informații despre baza de
date cum ar fi numele, locația, nume de utilizator și parolă, necesare pentru accesarea datelor
și informații despre provider-ul bazei de date.
Adaptorul de date definește o mapare de la baza de date la DataSet. Aceasta determină ce tip
de date sunt selectate din baza de date și care coloane din baza de date vor fi mapate pe
coloanele din DataSet.
Obiectele de tip DataSet stochează datele în interiorul aplicației. Acestea pot stoca unul sau
mai multe tabele și pot defini sau forța relații între tabele. De exemplu, baza de date folosită
anterior în acest capitol are un tabel Note care conține un câmp IDStudent. Valoarea din acest
câmp trebuie să se regăsească în valorile din tabelul Studenti, câmpul IDStudent. Aceasta
reprezintă o constrângere de tip foreign key. Obiectul DataSet poate reprezenta această
constrângere și semnala o eroare dacă programul încearcă să creeze o înregistrare în tabelul
Note cu o valoare a câmpului IDStudent care nu apare în tabelul Studenti.
Odată inițializată conexiunea împreună cu obiectele DataAdapter și DataSet, programul poate
apela metoda Fill() a obiectului DataAdapter pentru copierea datelor din baza de date în
DataSet. Mai târziu se poate apela metoda Update() pentru copierea oricăror modificări ale
înregistrărilor din DataSet înapoi în baza de date (Figura 7.21)

Figura 7.21. Obiectele de tip Connection, Data adapter și DataSet sunt folosite pentru mutarea datelor în/din
baza de date.

147
Medii și Tehnologii de Programare – curs

Dacă se compară Figura 7.21 cu Figura 7.20 se vor observa câteva similitudini. Ambele metode
folosesc un adaptor pentru a tranzita datele între baza de date și DataSet. La o primă privire
ar părea că în Figura 7.20 nu se folosește un obiect conexiune, dar de fapt obiectul
TableAdapter conține intern un obiect conexiune pentru accesarea bazei de date.
O diferență majoră este faptul că în Figura 7.20 se folosește un BindingSource și un
BindingNavigator pentru a-i permite utilizatorului să controleze BindingSource și să parcurgă
înregistrările.

7.5. Obiecte de tip Connection


Aceste obiecte sunt responsabile de conectarea aplicației la baza de date. Ele permit unui
DataAdapter să mute datele în/din DataSet.
Deși, la nivel primar, oferă aceleași proprietăți, există unele diferențe între obiectele
OleDbConnection, SqlConnection, OdbcConnection și OracleConnection.
Unele obiecte de tip Connnection pot lucra cu mai multe tipuri de baze de date. De exemplu,
obiectul OleDbConnection poate lucra cu orice tip de bază de date care suportă conexiuni
ODBC. În general, obiectele Connection care lucrează cu un tip specific de baze de date (cum
ar fi SqlConnection sau OracleConnection) oferă cele mai bune performanțe.
Tabelul 7.22 descrie câteva dintre cele mai folosite proprietăți puse la dispoziție de clasele
OleDbConnection și SqlConnection.
Proprietate Descriere
ConnectionString Stringul care definește conectarea la baza de date
ConnectionTimeout Timpul pe care obiectul îl așteaptă pentru a se conecta la baza de date. Dacă
acest timp expiră, se abandonează conectarea și se semnalează eroare.
Database Returnează numele bazei de date curente.
DataSource Returnează numele bazei de date curente sau numele serverului.
Provider (Doar pentru OleDbConnection) Returnează numele provider-ului bazei de date
OLEDB (de exemplu “Microsoft.Jet.OLEDB.4.0”).
ServerVersion Returnează numărul versiunii serverului bazei de date. Valoarea este valabilă
doar când conexiunea este deschisă și se exprimă sub forma “04.00.0000.”
State Returnează starea conexiunii. Poate lua valorile Closed, Connecting, Open,
Executing (execută o comandă), Fetching și Broken (conexiunea a fost deschisă și
apoi întreruptă; se poate închide și redeschide apoi conexiunea).

Tabelul 7.22. Proprietăți utile ale obiectelor Connection

Proprietatea ConnectionString include mai multe câmpuri separate prin punct și virgulă.
Textul următor arată o valoare tipică a proprietății ConnectionString pentru o conexiune
OleDbConnection care va accesa o bază de date Access.
Jet OLEDB:Global Partial Bulk Ops=2;
Jet OLEDB:Registry Path=;
Jet OLEDB:Database Locking Mode=1;
Data Source="D:\Work\Angajati.mdb";
Mode=Share Deny None;Jet OLEDB:Engine Type=5;
Provider="Microsoft.Jet.OLEDB.4.0";
Jet OLEDB:System database=;
Jet OLEDB:SFP=False;
persist security info=False;
Extended Properties=;
Jet OLEDB:Compact Without Replica Repair=False;
Jet OLEDB:Encrypt Database=False;
Jet OLEDB:Create System Database=False;

148
Baze de date în Visual C# .NET

Jet OLEDB:Don’t Copy Locale on Compact=False;


User ID=Admin;
Jet OLEDB:Global Bulk Transactions=1;

Multe dintre câmpurile separate prin punct și virgulă sunt opționale și pot fi omise. Ar fi destul
de complicat să ne amintim care sunt câmpurile obligatorii și care sunt cele opționale, însă,
din fericire, nu este necesar. În loc să compunem noi proprietatea ConnectionString, putem
lăsa Visual C# să o alcătuiască pentru noi. Pentru aceasta, afișăm fereastra Server Explorer
(meniul View –> Server Explorer), precum se poate observa în Figura 7.23.

Figura 7.23. Fereastra Server Explorer

Următorul fragment de cod ilustrează crearea, deschiderea, folosirea și închiderea unui obiect
OleDbConnection.
using System.Data.OleDb;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
// ...

private void Form1_Load(object sender, EventArgs e)


{
// Creeaza conexiunea.
OleDbConnection conn = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;
Data Source=D:\Work\Catalog.accdb;
Persist Security Info=True;User ID=Admin;Password=;");

// Deschide conexiunea.
conn.Open();

// ...
// Inchide conexiunea.
conn.Close();
conn.Dispose();
}
}
}

Tabelul 7.24 prezintă cele mai des folosite metode propuse de clasele OleDbConnection și
SqlConnection.
Metoda Descriere
BeginTransaction Începe o tranzacție cu baza de date și returnează un obiect de tip tranzacție. O
tranzacție asigură faptul că toate comenzile dintr-o secvență de comenzi sunt
executate, în caz contrar operația fiind anulată.
ChangeDatabase Modifică baza de date curentă.
Close Închide baza de date curentă.
CreateCommand Creează un obiect de tip comandă care poate executa unele acțiuni asupra bazei
de date, cum ar fi selectarea de înregistrări, crearea de tabele, modificarea unor
înregistrări, etc.
Open Deschide o conexiune cu valorile specificate în proprietatea ConnectionString

Tabelul 7.24. Metode utile ale obiectelor Connection.

149
Medii și Tehnologii de Programare – curs

Cele mai utile evenimente ale obiectelor de tip Connection sunt InfoMessage și StateChange.
Evenimentul InfoMessage apare când provider-ul de bază de date semnalează o avertizare sau
un mesaj de informare. Programul poate citi mesajul și, în consecință, poate efectua o acțiune
sau, pur și simplu, îl afișează utilizatorului. Evenimentul StateChange apare când se modifică
starea conexiunii la baza de date.
Metodele Fill() și Update() ale unui obiect DataAdapter deschid automat o conexiune,
efectuează acțiunile, apoi închid conexiunea, astfel încât utilizatorul nu este nevoit să
gestioneze conexiunile. De exemplu, când programul apelează metoda Fill(), adaptorul
deschide rapid o conexiune, copiază datele din baza de date în DataSet și apoi închide
conexiunea.

7.6. Obiecte de tip DataAdapter


Un obiect de tip DataAdapter transferă datele între o conexiune și un DataSet. Metodele cele
mai importante ale acestui obiect sunt Fill() și Update(), care mută datele în și din DataSet.
Un DataAdapter oferă, de asemenea, alte proprietăți și metode care pot fi folositoare. Tabelul
7.25 prezintă cele mai folositoare proprietăți ale obiectelor de tip DataAdapter.
Proprietate Descriere
DeleteCommand Obiectul de tip Command pe care obiectul DataAdapter îl folosește pentru a
șterge înregistrări.
InsertCommand Obiectul de tip Command pe care DataAdapter-ul îl folosește pentru a insera
înregistrări.
SelectCommand Obiectul de tip Command pe care DataAdapter-ul îl folosește pentru a selecta
înregistrări.
TableMappings O colecție de obiecte DataTableMapping care determină modul în care vor fi
mapate tabelele din baza de date în DataSet. Fiecare obiect are o colecție
ColumnMappings care va determina modul în care vor fi mapate coloanele din
tabele în tabelele din DataSet.
UpdateCommand Obiectul de tip Command pe care DataAdapter-ul îl folosește pentru a modifica
înregistrări.

Tabelul 7.25. Proprietăți utile ale obiectelor DataAdapter.

Există mai multe modalități de creare a obiectelor de tip Command. De exemplu, dacă pentru
construirea adaptorului folosim Data Adapter Configuration Wizard, atunci wizardul creează
automat aceste obiecte (vom vedea în continuare cum). Putem selecta adaptorul și expanda
obiectele de tip Command în fereastra Properties, pentru a le vizualiza proprietățile.
Data Adapter Configuration Wizard vă ajută la setarea proprietăților unui nou adaptor de date
sau a unuia existent. Un adaptor de date conține comenzi SQL pe care aplicația le poate utiliza
pentru citirea datelor dintr-o bază de date într-un DataSet și scrierea lor înapoi. Wizard-ul
poate opțional să creeze o conexiune de date care permite adaptorului să comunice cu o bază
de date.
O altă modalitate de creare a acestor comenzi este folosirea unui obiect CommandBuilder.
Dacă atașăm un astfel de obiect adaptorului, acesta va folosi obiectul CommandBuilder pentru
a genera comenzile de care are nevoie, în mod automat.
Următoarea secvență de cod ilustrează modul în care un program poate asocia un obiect de
tip OleDbCommandBuilder la un OleDbDataAdapter. Când se apelează metoda Update(),
adaptorul folosește obiectul CommandBuilder, dacă este necesar, pentru a efectua comenzi de
inserare, modificare sau ștergere asupra bazei de date. Metoda Debug.WriteLine() va afișa
textul comenzilor generate în mod automat.

150
Baze de date în Visual C# .NET

private void Form1_Load(object sender, EventArgs e)


{
// Ataseaza un command builder la adaptorul de date si afiseaza comenzile generate.
OleDbConnection con = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0;
Data source=D:\Work\temp\Catalog.accdb;User ID=Admin;Password=;");
con.Open();
OleDbDataAdapter dataAdapter = new OleDbDataAdapter(
new OleDbCommand("SELECT * FROM Studenti", con));
OleDbCommandBuilder cmdBuilder = new OleDbCommandBuilder(dataAdapter);
Debug.WriteLine(cmdBuilder.GetDeleteCommand().CommandText);
Debug.WriteLine(cmdBuilder.GetInsertCommand().CommandText);
Debug.WriteLine(cmdBuilder.GetUpdateCommand().CommandText);
}

Textul următor afișează rezultatele obținute. Obiectul de tip CommandBuilder generează


aceste comenzi pe baza interogării "SELECT * FROM Studenti" care a fost încărcată în DataSet.
DELETE FROM Studenti WHERE ((IDStudent = ?) AND ((? = 1 AND Nume IS NULL) OR (Nume = ?)) AND
((? = 1 AND Prenume IS NULL) OR (Prenume = ?)))
INSERT INTO Studenti (Nume, Prenume) VALUES (?, ?)
UPDATE Studenti SET Nume = ?, Prenume = ? WHERE ((IDStudent = ?) AND ((? = 1 AND Nume IS
NULL) OR (Nume = ?)) AND ((? = 1 AND Prenume IS NULL) OR (Prenume = ?)))

Proprietatea TableMappings a adaptorului, permite modificarea felului în care adaptorul


mapează datele din baza de date în DataSet. De exemplu, am putea face o copie a tabelului
Studenti din baza de date în DataSet, numita „Tineri”. De obicei, nu este nevoie să modificăm
numele tabelului sau a coloanelor, totuși aceste modificări se pot face interactiv în modul
design mult mai ușor decât în cod, astfel că, de obicei, aceste valori se vor lăsa nemodificate.
Pentru a crea un data adaptor în modul design, trebuie să deschidem un formular, selectăm
din meniul Toolbox opțiunea Data și apoi dublu click pe controlul DataAdapter (dacă nu apare
controlul DataAdapter în ToolBox, atunci facem click dreapta pe ToolBox, selectăm meniul
Choose Items, iar de acolo selectăm adaptorul dorit, de exemplu, OleDbDataAdapter).
La crearea unui DataAdapter va apărea Data Adapter Configuration Wizard (vezi Figura 7.26).
Primul pas este similar celui descris anterior pentru configurarea unei noi conexiuni. Selectăm
o conexiune deja existentă sau apăsăm butonul New Connection pentru una nouă.

Figura 7.26. Data Adapter Configuration Wizard ne ajuta să definim un adaptor nou

La apăsarea butonului „Next” va apărea un dialog ca cel din Figura 7.27. De aici putem selecta
metoda cu care adaptorul va opera asupra bazei de date și va determina modul în care datele
vor fi selectate, inserate sau modificate în baza de date. Dacă selectăm opțiunea “Use SQL

151
Medii și Tehnologii de Programare – curs

Statements”, atunci adaptorul va lucra cu instrucțiuni simple SQL. Dacă selectăm opțiunea
“Create new stored procedures”, adaptorul va genera noi proceduri stocate în baza de date.
Pentru ca wizardul să folosească proceduri stocate existente, selectăm opțiunea „Use existing
stored procedures”. În Figura 7.27 prima opțiune este singura disponibilă pentru un
OleDbDataAdapter atașat unei baze de date Access, așa cum am folosit în acest exemplu.

Figura 7.27. Selectarea unei metode prin care adaptorul va opera asupra bazei de date

Dacă selectăm “Use SQL Statements” și apăsăm butonul „Next”, va apărea dialogul din Figura
7.28.

Figura 7.28. Generarea interogării SQL

Dacă avem experiență în lucrul cu interogările SQL, atunci putem introduce manual o
interogare SQL pe care adaptorul o va folosi când va selecta datele din baza de date. În caz
contrar, putem da click pe butonul „Query Builder” (vezi Figura 7.29), apoi vom selecta
tabelele din baza de date care conțin înregistrările pe care vrem să le folosim și dăm click pe
butonul „Add”. După ce am selectat tabelele închidem dialogul „Add Table”. Coloanele din al
doilea panou pot fi utilizate pentru determinarea modului în care sunt sortate câmpurile. În al
treilea panou este afișată comanda SQL pe care o construim. Putem da click pe butonul

152
Baze de date în Visual C# .NET

„Execute Query” pentru rularea interogării SQL și afișarea rezultatelor în partea de jos. Când
am terminat, apăsăm butonul „OK”.

Figura 7.29. Putem utiliza instrumentul Query Builder pentru definirea datelor pe care le va folosi adaptorul.

După ce apăsăm butonul „Next”, Data Adapter Configuration Wizard va afișa un sumar similar
celui din Figura 7.30. Acest sumar descrie acțiunile pe care wizard-ul le va executa și pe cele
pe care nu le va executa. În funcție de interogarea folosită pentru selectarea datelor, wizard-
ul s-ar putea să nu genereze toate comenzile de selectare, modificare, inserare sau ștergere a
înregistrărilor. De exemplu, dacă interogarea cuprinde mai multe tabele, wizard-ul nu va fi
capabil să își dea seama cum să modifice înregistrările, așa că nu va genera comenzi de
inserare, modificare sau ștergere.

Figura 7.30. Sumarul generat de Data Adapter Configuration Wizard

153
Medii și Tehnologii de Programare – curs

Când apăsăm comanda „Finish”, wizard-ul creează un nou adaptor și un nou obiect de tip
conexiune care va fi asociat adaptorului. Se vor seta proprietățile DeleteCommand, InsertCommand,
SelectCommand și UpdateCommand ale adaptorului în concordanță cu conexiunea la baza de date
pe care am selectat-o. De asemenea, se generează mapări inițiale ale tabelelor pentru a
transforma valorile din baza de date în valori pentru DataSet.
Configurarea unui adaptor de date este unul din pașii necesari pentru utilizarea unui DataSet
în cadrul aplicației. După rularea wizard-ului, veți mai avea nevoie să adăugați separat un
DataSet la aplicația dumneavoastră și să scrieți cod care să furnizeze pentru adaptorul de date
o modalitate de lucru cu DataSet-ul.

În versiunile anterioare ale Visual Studio, adaptoarele de date erau utilizate pentru
comunicarea dintre aplicație și o bază de date. Deși adaptoarele de date sunt încă o
componentă de bază a .NET Framework Data Providers (ADO .NET), componentele
TableAdapter, generate automat de către designer, simplifică procesul de
manipulare a datelor între o aplicație și o bază de date.

7.7. Obiecte de tip Command


Clasele obiectelor de tip Command (OleDbCommand, SqlCommand, OdbcCommand și
OracleCommand) definesc comenzile pentru manipularea datelor dintr-o bază de date.
Acestea pot fi interogări SQL sau alte comenzi, cum ar fi INSERT, UPDATE, DELETE sau
CREATE TABLE.
Proprietatea Connection a obiectului furnizează conexiunea la baza de date pe baza căreia se
vor executa comenzile. Proprietatea CommandText oferă textul SQL pe baza căruia se vor executa
comenzile.
Proprietatea CommandType va stoca tipul comenzii conținut de obiectul de tip Command. Acesta
poate fi:
• StoredProcedure (CommandText va conține numele procedurii stocate)
• TableDirect (CommandText va conține numele unuia sau mai multor tabele din care vor
fi furnizate datele)
• Text (CommandText va conține comanda SQL).
În colecția Parameters a obiectului de tip Command vor fi stocați parametrii care vor defini
orice valoare necesară pentru a executa comanda. De exemplu, codul următor creează un
obiect de tip OleDbCommand care va executa comanda SQL "INSERT INTO Studenti (IDStudent,
Nume, Prenume) VALUES (?, ?, ?)". Semnele de întrebare marchează locul parametrilor care
vor fi adăugați mai târziu. Apoi se vor adăuga în cod două obiecte noi de tip OleDbParameter
la colecția Parameters a comenzii. Când în cod se invoca metoda ExecuteNonQuery(), adaptorul
înlocuiește semnele de întrebare cu valorile parametrilor în ordinea în care apar în colecția
Parameters. În acest exemplu, valoarea din txtID.Text înlocuiește primul semn de întrebare,
valoarea din txtNume.Text înlocuiește al doilea semn de întrebare, iar valoarea txtPrenume.Text
al treilea semn de întrebare.
private void btnAdauga_Click(object sender, EventArgs e)
{
// Deschide conexiunea
string conString = @"Provider=Microsoft.ACE.OLEDB.12.0;
Data source=D:\Work\Catalog.accdb;User ID=Admin;Password=;";
OleDbConnection connStudenti = new OleDbConnection(conString);
connStudenti.Open();

154
Baze de date în Visual C# .NET

// Creeaza un obiect Command pentru inserarea datelor


OleDbCommand cmd = new OleDbCommand(@"INSERT INTO Studenti(IDStudent,Nume,Prenume)
VALUES (?, ?, ?) ", connStudenti);

// Adauga parametrii pentru obiectul comanda


cmd.Parameters.Add(new OleDbParameter("IDStudent", txtID.Text));
cmd.Parameters.Add(new OleDbParameter("FirstName", txtNume.Text));
cmd.Parameters.Add(new OleDbParameter("LastName", txtPrenume.Text));

// Execută comanda
try
{
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}

// Afiseaza datele
AfisareValori(connStudenti);

// Inchide conexiunea
connStudenti.Close();
connStudenti.Dispose();
}

Obiectele de tip Command oferă câteva metode utile (vezi Tabelul 7.31), dintre care trei
pentru executarea unor comenzi SQL.
Metodă Descriere
ExecuteNonQuery() Execută o comandă care nu este o interogare și care nu returnează nici o valoare.
ExecuteScalar() Execută o comandă și returnează prima coloană din prima înregistrare găsită.
Este util atunci când se execută comenzi care returnează o singură valoare (de
exemplu, "SELECT COUNT * FROM Studenti").
ExecuteReader() Execută o interogare SQL și returnează un obiect de tip DataReader (de exemplu,
OleDbDataReader). Programul poate folosi acest obiect pentru a naviga printre
înregistrările returnate.
CreateParameter() Adaugă obiecte noi la colecția Parameters a obiectului.
Prepare() Compilează comanda într-o formă în care va fi executată mai rapid de baza de
date.

Tabelul 7.31. Metode utile ale obiectelor de tip Command

7.8. Obiectul DataSet


DataSet este cel mai important obiect folosit pentru stocarea în memorie a datelor dintr-o bază
de date. El oferă toate instrumentele pentru construirea, încărcarea, manipularea și salvarea
datelor, într-un mod similar celui folosit la bazele de date relaționate. Un DataSet poate stoca
tabele multiple cu relații complexe părinte-copil și chei unice. Acesta oferă metode pentru
combinarea DataSet-urilor, căutarea de înregistrări care îndeplinesc un anumit criteriu, sau
pentru salvarea datelor în diferite moduri (bază de date relaționată sau fișier XML). Din multe
puncte de vedere, putem spune că un DataSet este o bază de date stocată în memorie, iar nu
pe disc.
Unul dintre cele mai răspândite moduri folosire a unui DataSet este încărcarea, la pornirea
programului, a datelor dintr-o bază de date relațională și folosirea unor controale pentru
afișarea înregistrărilor. Utilizatorul va putea manipula datele interactiv, iar la sfârșit, când

155
Medii și Tehnologii de Programare – curs

programul își încheie execuția, modificările vor fi salvate în baza de date. Alte variante sunt
încărcarea datelor dintr-un XML, respectiv construirea unui DataSet în memorie, fără
utilizarea unei baze de date. Programul poate folosi controale pentru a se conecta la DataSet
iar utilizatorul va putea vizualiza și manipula date complexe.
Secvența de cod prezentată în continuare creează și inițializează un DataSet și începe prin
crearea unui nou DataSet numit „Catalog”. Este creat apoi un DataTable numit „Studenti”, care
este adăugat la colecția de tabele a DataSet-ului. Sunt adăugate la coloanele obiectului
DataTable noi coloane: Nume, Prenume și IDStudent. Se setează apoi pe true proprietatea
Unique a coloanei IDStudent, astfel nefiind permise valori duplicate în coloana IDStudent.
Se creează apoi un vector de obiecte de tip DataColumn în care se introduc referințele către
coloanele Nume și Prenume. Acest vector este folosit pentru crearea unei constrângeri
UniqueConstraint adăugată la colecția Constraints a tabelului. Prin aceasta se asigură că fiecare
pereche de Nume+Prenume este unică.
În mod similar se creează tabelul Note având coloanele IDStudent, Disciplina și Nota, apoi se
adaugă o constrângere UniqueConstraint, astfel încât fiecare pereche IDStudent+Nota să fie
unică.
Este adăugată o relație între tabelul Studenti, coloana IDStudent și tabelul Note, coloana
IDStudent, după care cele două tabele sunt populate cu câteva înregistrări.
În final, programul atașează tabelele la două controale DataGridView pentru afișarea
rezultatelor. Utilizatorul poate folosi controalele DataGridView pentru examinarea și
modificarea datelor, ca și cum ar fi fost încărcate din baza de date.
private void Form1_Load(object sender, EventArgs e)
{
// Creeaza DataSet-ul.
DataSet dsCatalog = new DataSet("Catalog");

// Creeaza tabelul Studenti.


DataTable dtStudenti = dsCatalog.Tables.Add("Studenti");

// Adauga coloane la tabelul Studenti.


dtStudenti.Columns.Add("IDStudent", typeof(int));
dtStudenti.Columns.Add("Nume", typeof(string));
dtStudenti.Columns.Add("Prenume", typeof(string));

// Face campul IDStudent unic.


dtStudenti.Columns["IDStudent"].Unique = true;

// Face campul combinat Nume+Prenume unic.


DataColumn[] colNumePrenume = { dtStudenti.Columns["Nume"],
dtStudenti.Columns["Prenume"] };
dtStudenti.Constraints.Add(new UniqueConstraint(colNumePrenume));

// Creeaza tabelul Note.


DataTable dtNote = dsCatalog.Tables.Add("Note");

// Adauga coloane la tabelul Note.


dtNote.Columns.Add("IDStudent", typeof(int));
dtNote.Columns.Add("Disciplina", typeof(string));
dtNote.Columns.Add("Nota", typeof(int));

// Face campul combinat IDStudent/Disciplina unic.


DataColumn[] colStudentDisciplina = { dtNote.Columns["IDStudent"],
dtNote.Columns["Disciplina"] };
dtNote.Constraints.Add(new UniqueConstraint(colStudentDisciplina));

// Creeaza o relatie intre doua tabele prin campul IDStudent.


dsCatalog.Relations.Add("Studenti_Note", dtStudenti.Columns["IDStudent"],
dtNote.Columns["IDStudent"]);

156
Baze de date în Visual C# .NET

// Adauga cateva date ale studentilor.


dtStudenti.Rows.Add(new object[] { 1, "Popescu", "Ion" });
dtStudenti.Rows.Add(new object[] { 2, "Buga", "Cristina" });
dtStudenti.Rows.Add(new object[] { 3, "Popa", "Andrei" });
dtStudenti.Rows.Add(new object[] { 4, "Dumitru", "Ana" });

// Adauga si cateva note aleatoare.


Random nota = new Random();
dtNote.Rows.Add(new object[] { 1, "MTP", nota.Next(5, 10) });
dtNote.Rows.Add(new object[] { 2, "MTP", nota.Next(5, 10) });
dtNote.Rows.Add(new object[] { 3, "MTP", nota.Next(5, 10) });
dtNote.Rows.Add(new object[] { 4, "MTP", nota.Next(5, 10) });

// Ataseaza tabelele la controale DataGridView.


grdStudenti.DataSource = dtStudenti;
grdNote.DataSource = dtNote;
}

Tabelul 7.32 descrie cele mai folositoare proprietăți ale obiectelor DataSet.
Proprietate Descriere
CaseSensitive Determină dacă string-urile din DataTable sunt comparate case sensitive.
DataSetName Numele DataSet-ului. Dacă vom folosi reprezentarea XML, această
proprietate va seta numele elementului rădăcină.
DefaultViewManager Returnează un obiect DataViewManager pe care îl putem folosi pentru crea o
vizualizare personalizată a datelor din DataSet care să permită filtrare, căutare
și navigare.
EnforceConstraints Determină dacă sunt respectate constrângerile la operațiile de actualizare a
datelor.
HasErrors Returnează true dacă sunt erori în vreunul din tabelele din DataSet.
Prefix Returnează sau setează un prefix XML ca alias pentru spațiul de nume al
DataSet-ului.
Relations O colecție de obiecte de tip DataRelation care reprezintă relații părinte-copil
între coloanele din diferite tabele.
Tables O colecție de obiecte de tip DataTable care reprezintă tabelele stocate în
DataSet.

Tabelul 7.32. Proprietăți utile ale obiectelor DataSet.

Tabelul 7.33 descrie cele mai folosite metode ale obiectelor DataSet.
Metoda Descriere
AcceptChanges Operează toate modificările care au fost făcute de la încărcarea datelor
sau de când s-a apelat ultima oară AcceptChanges.
Clear Șterge toate înregistrările din toate tabelele din DataSet.
Clone Efectuează o copie a DataSet-ului, incluzând structura tabelelor,
relațiile și constrângerile, însă fără a include datele.
Copy Efectuează o copie a DataSet-ului, incluzând structura tabelelor,
relațiile și constrângerile, incluzând și datele.
GetChanges Efectuează o copie a DataSet-ului, în care vor fi copiate doar
înregistrările care au fost modificate de la încărcarea datelor sau de la
ultima apelare a metodei AcceptChanges().
GetXml Returnează un string conținând reprezentarea XML a datelor stocate în
DataSet.
GetXmlSchema Returnează schema XML pentru reprezentarea XML a datelor stocate
în DataSet.
HasChanges Returnează true dacă tabelele din DataSet conțin modificări.
Merge Adaugă un DataSet, DataTable sau șir de obiecte DataRow la DataSet.
ReadXml Citește datele din XML în DataSet.

157
Medii și Tehnologii de Programare – curs

ReadXmlSchema Citește schema XML în DataSet.


RejectChanges Anulează toate modificările făcute de când s-a încărcat DataSet-ul sau
de la ultima apelare a metodei AcceptChanges().
WriteXml Scrie datele din DataSet într-un XML.
WriteXmlSchema Scrie structura DataSet-ului într-un fișier sub forma unei scheme XML.
Tabelul 7.33. Metode utile ale obiectelor DataSet.

Câteva dintre aceste metode sunt conținute și de către alte obiecte. De exemplu, metoda
HasChanges() returnează true dacă un tabel din DataSet conține modificări. Obiectele
DataTable și DataRow au de asemenea metoda HasChanges() care returnează true dacă acestea
conțin modificări. Alte metode de acest fel ar mai fi AcceptChanges(), Clear(), Clone(), Copy(),
GetChanges() și RejectChanges().

7.9. Obiectul DataTable


Clasa DataTable reprezintă datele dintr-un tabel din DataSet. Un obiect DataTable conține
obiecte de tip DataRow, pentru reprezentarea înregistrărilor, obiecte de tip DataColumn care
definesc coloanele tabelului, obiecte de tip Constraints și obiecte care reprezintă relațiile
dintre tabele. Clasa DataTable oferă de asemenea metode și evenimente pentru manipularea
înregistrărilor.
Tabelul 7.34 descrie cele mai folosite proprietăți ale obiectului DataTable.
Proprietate Descriere
CaseSensitive Determină dacă string-urile din DataTable sunt comparate case sensitive
ChildRelations O colecție de obiecte de tip DataRelation care definește relații părinte-copil,
unde tabelul este părintele.
Columns O colecție de obiecte de tip DataColumn care definește coloanele tabelului
(numele coloanei, tipul de date, valoarea implicita, lungime maximă etc.)
Constraints O colecție de obiecte de tip Constraints care reprezintă constrângerile asupra
bazei de date. ForeignKeyConstraint cere ca unele valori dintr-un tabel să fie
prezente în alt tabel. UniqueConstraint cere ca o valoare să fie unică într-un
tabel.
DataSet DataSet-ul care conține obiectul DataTable.
DefaultView Returnează un obiect DataView unde putem sorta și filtra sau căuta în
înregistrările din tabel.
HasErrors Returnează true dacă una din înregistrările din DataTable conține o eroare.
MinimumCapacity Dimesiunea inițială a tabelului.
ParentRelations O colecție de obiecte de tip DataRelation care definește relații părinte-copil,
unde tabelul este copilul.
Prefix Spațiul de nume pentru reprezentarea XML a datelor din DataTable.
PrimaryKey Un vector de coloane care funcționează ca chei primare ale tabelului.
Rows O colecție de obiecte DataRow care conține înregistrările din tabel.
TableName Numele tabelului.

Tabelul 7.34. Proprietăți utile ale obiectelor DataTable

Cele mai folosite metode ale obiectelor DataTable sunt prezentate în Tabelul 7.35:
Metoda Descriere
AcceptChanges() Acceptă toate modificările care au fost făcute de la încărcarea datelor sau de la
ultima apelare a metodei AcceptChanges().
Clear() Șterge toate înregistrările din DataTable.

158
Baze de date în Visual C# .NET

Clone() Efectuează o copie a DataTable, incluzând tabelele, relațiile și constrângerile,


fără a include însă datele.
Compute() Calculează valoarea unei expresii folosind înregistrările care satisfac condițiile
de filtrare.
Copy() Creează o copie a DataTable, incluzând tabelele, relațiile și constrângerile
incluzând datele.
GetChanges() Efectuează o copie a DataTable, în care vor fi copiate doar înregistrările
modificate.
GetErrors() Returnează un șir de obiecte DataRow care conțin erori.
ImportRow() Copiază datele dintr-un DataRow în DataTable.
LoadDataRow() Caută și actualizează o anumită înregistrare. Dacă nu este găsită nicio
înregistrare care să corespundă valorilor transmise ca parametri, este creată o
nouă înregistrare folosind valorile respective.
NewRow() Creează un obiect nou de tip DataRow care are aceeași schemă cu a tabelului.
RejectChanges() Anulează toate modificările făcute de la încărcarea datelor sau de la ultimul
apel al metodei AcceptChanges().
Select() Returnează un vector de obiecte DataRow care îndeplinesc criteriul de filtrare.

Tabelul 7.35. Metode utile ale obiectelor DataTable

Evenimentele cele mai folosite pentru obiectele DataTable sunt prezentate în Tabelul 7.36.
Eveniment Descriere
ColumnChanged Apare după ce o valoare a fost modificată într-o anumită coloană dintr-o
înregistrare.
ColumnChanging Apare în timp ce o valoare este modificată într-o anumită coloană dintr-o
înregistrare.
RowChanged Apare după ce o înregistrare a fost modificată cu succes.
RowChanging Apare în timp ce este modificată o înregistrare.
RowDeleted Apare după ce o înregistrare a fost ștearsă.
RowDeleting Apare înainte ca o înregistrare să fie ștearsă.

Tabelul 7.36. Evenimente utile ale obiectelor DataTable

Întrebări și exerciții:
1. Rememorați secvența de acțiuni necesare pentru legarea automată a unei aplicații C#
la o bază de date. Creați o aplicație care și conectați-o la o bază de date creată de voi.
2. Care sunt obiectele generate automat după legarea automată a aplicației la o bază de
date? Precizați semnificația fiecăruia.
3. Ce reprezintă obiectele DataSet și DataTable?
4. Implementați comenzi de adăugare și ștergere a unor înregistrări folosind obiecte de tip
Command.

159