Sunteți pe pagina 1din 15

1

Seminar 8 PAW


Lucrul cu baze de date in C# - tehnologia ADO.NET

Accesul la comenzi SQL din C# se face prin:
- interfata ODBC (Open Data Base Connectivity);
- setul de date OLEDB (Object Linking and Embedding);
ADO.NET (Active Data Object) este o tehnologie de acces la date care
disponibilizeaza clase, interfete, structuri si enumerari pentru accesul la baze de date sub
.NET Framework.
Obiectele prin care se implementeaza accesul la o baza de date sunt: conexiunea,
adaptorul si setul de date.

Conexiunea la baza de date

Cei mai frecventi furnizori de date (Data Provider) sunt:
- SQL Server .NET Data Provider, pentru care se foloseste un obiect de tip
SqlConnection definit in namespace-ul System.Data.SqlClient pentru realizarea
conexiunii;
- OLE DB .NET Data Provider, care foloseste un obiect de tip OleDbConnection
definit in System.Data.OleDb;
- ODBC .NET Data Provider, foloseste un obiect OdbcConnection definit in
System.Data.Odbc.

Starile unei conexiuni sunt:
- Connecting in curs de conectare;
- Open conexiune deschisa;
- Executing in derularea unei conexiuni;
- Fetching in timpul unei cautari in baza de date.

DataSet si DataView

Obiectul DataSet se mai numeste si container de date. Schimburile de date dintre un
DataSet si baza de date sunt mediate cu ajutorul unui obiect DataAdapter, a carui principala
metoda, Fill(dataSet, tabela), incarca cu date o tabela dintr-un DataSet.
Fiecare DataAdapter mediaza transferul de date intre un singur obiect DataTabledin
DataSet si rezultatul unei singure interogari printr-o comanda SQL.
Un DataSet poate contine mai multe obiecte DataTable, cate unul pentru fiecare
tabela din baza de date.
Clasa DataView ofera un mod de vizualizare a unui obiect DataSet, oferind
posibilitatea filtrarii datelor dintr-o tabela. Aceleasi tabele ale unui DataSet pot avea mai
multe vizualizari asociate, reprezentand puncte de vedere diferite ale unor utilizatori.

Obiecte de tip Command

Clasele de tip Command (SqlCommand si OleDbCommand) sunt folosite pentru a
executa o comanda SQL sau proceduri stocate. Exemple de constructori ale acestor clase:


2
OleDbCommand cmd1 = new OleDbCommand(SELECT * from student, conexiune);
SqlCommand cmd2 = new SqlCommand();
cmd2.CommandText = SELECT * from student;
cmd2.Connection = conexiune;

Comenzile de acces direct la baza de date sunt de 3 tipuri:
- ExecuteReader, care intoarce o colectie de linii de date, accesibile linie cu linie;
- ExecuteScalar, care returneaza o singura valoare, de tip generic object;
- ExecuteNonQuery, care nu returneaza nimic, dar executa actualizarile asupra bazei de
date.

Lucrul cu proceduri stocate

Procedurile stocate sunt cereri frecvent folosite asupra unei baze de date, grupate sub
un nume de apel. Ele au doua avantaje majore:
- sunt stocate pe server si nu au nevoie sa fie compuse si retransmise de fiecare data
cand sunt invocate;
- sunt deja compilate, fiind lansate direct in executie si beneficiind de utilizarea
statisticilor interne pentru optimizarea accesului la datele unei tabele.


Aplicatia 1:

Enunt:

Sa se creeze o aplicatie Windows care permite prelucrarea, prin intermediul
butoanelor de pe un formular, a datelor stocate intr-o baza de date Microsoft Access. Baza de
date se numeste student.mdb / student.accdb si contine o tabela student, avand urmatoarea
structura:



Comanda SQL pentru crearea tabelei student este urmatoarea:

CREATE TABLE student(
COD INT PRIMARY KEY,
NUME VARCHAR(10),
VARSTA INT,
INALTIME INT,
CNP VARCHAR(13),
SEX VARCHAR(2),
FORMA VARCHAR(10));

3
Aplicatia va implementa conexiuni la baza de date pentru executarea tranzactiilor
asupra acesteia.

Aspecte teoretice:

Un .NET data provider este utilizat pentru conectarea la o baz de date, pentru a se
executa comenzi i pentru a gestiona rezultate. Aceste rezultate sunt, fie procesate direct,
utiliznd o component DataReader, sau sunt plasate ntr-un DataSet pentru a fi
combinate cu alte informaii i pentru a fi prelucrate ulterior. Exist 4 obiecte de baz ce
definesc un .NET data provider:

Obiect Descriere
Connection Stabiliete o conexiune cu o surs de
date.
Command Execut comenzi la surs. Prezint o
lista de Parameters i poate emite o
Transaction n cadrul unei conexiuni
Connection.
DataReader Extrage un stream read-only de date
dintr-o surs.
DataAdapter Populeaz un DataSet i rezolv
update-ul cu sursa.

Rezolvare:

Pe un Form1 se aduc din ToolBox urmatoarele controale: zece butoane si un
textBox1, ca in figura de mai jos:



4
Textbox-ul va avea proprietatea Multiline setata pe True si va servi pentru incarcarea
datelor din tabela student.
Aplicatia va mai contine un Form2 care se apeleaza prin apasarea butonului Update
varsta de pe Form1. Adaugarea acestui formular se face din fereastra Solution Explorer
prin click dreapta pe numele aplicatiei si Add New Item Windows Form. Pe Form2 se
adauga doua label-uri, doua textbox-uri si un buton, ca in figura de mai jos:



Pentru recunoasterea elementelor de conexiune la baza de date, este nevoie de
includerea namespace-ului urmator in ambele forme:

using System.Data.OleDb;

String-ul de conexiune la baza de date se initializeaza in constructorul fiecarei forme,
astfel:

string AccessProvider;

public Form1()
{
InitializeComponent();
//AccessProvider = "Provider = Microsoft.Jet.OLEDB.4.0; Data Source =
student.mdb";
AccessProvider = "Provider = Microsoft.ACE.OLEDB.12.0; Data Source =
student.accdb";
}

Pe evenimentul Click al primului buton din Form1, Citire BD, se pune codul sursa
de mai jos:

private void button1_Click(object sender, EventArgs e)
{
textBox1.Text = "";
// se defineste obiectul pentru conexiune
OleDbConnection conexiune = new OleDbConnection(AccessProvider);
// se defineste comanda de interogare
string stringSQL = "SELECT * from student";
// se defineste obiectul pentru comanda de executat
5
OleDbCommand comanda = new OleDbCommand(stringSQL, conexiune);
try
{
// se deschide conexiunea
conexiune.Open();
// se defineste un obiect DataReader pt a retine datele
OleDbDataReader myDataReader = comanda.ExecuteReader();
textBox1.Text = "Cod, Nume, Varsta, Inaltime, CNP, Sex, Forma";
// ExecuteReader returneaza un DataReader
while (myDataReader.Read())
{
textBox1.Text += "\r\n" + myDataReader["cod"] + " , " +
myDataReader["nume"] + " , " + myDataReader["varsta"] + "
, " + myDataReader["inaltime"] + " , " +
myDataReader["CNP"] + " , " + myDataReader["sex"] + " , "
+ myDataReader["forma"];
}
myDataReader.Close();
}
catch (Exception er)
{
// se trateaza exceptiile
MessageBox.Show(er.Message);
}
finally
{
// se inchide (obligatoriu) conexiunea
conexiune.Close();
}
}

Prin apasarea butonului de Citire BD se vor incarca in textBox1 toate inregistrarile
existente in tabela student din baza de date.


6

Pe evenimentul Click al butonului Update varsta se pune codul sursa de mai jos:

private void button2_Click(object sender, EventArgs e)
{
Form2 fupdate = new Form2();
fupdate.ShowDialog();
}

Update-ul efectiv se va realiza prin apasarea butonului Modifica de pe Form2. Pe
evenimentul Click al butonului Modifica se pune urmatorul cod:

private void button1_Click(object sender, EventArgs e)
{
string nume = textBox1.Text;
int varsta = 0;
try
{
varsta = Convert.ToInt16(textBox2.Text);
}
catch (Exception er)
{
MessageBox.Show(er.Message);
}
OleDbConnection conexiune = new OleDbConnection(AccessProvider);
string stringSQL = "UPDATE student set varsta=" + varsta + " WHERE
nume='" + nume + "' ";
OleDbCommand comanda = new OleDbCommand(stringSQL, conexiune);
try
{
// se deschide conexiunea
conexiune.Open();
// se executa comanda si se memoreaza numarul de inregistrari
afectate
int n = comanda.ExecuteNonQuery();
MessageBox.Show("Au fost modificate " + n + " inregistrari!");
}
catch (Exception er)
{
MessageBox.Show(er.Message);
}
finally
{
// se inchide conexiunea
conexiune.Close();
}
}

Actiunea Update varsta presupune modificarea varstei tuturor studentilor cu un
anumit nume introdus de la tastatura. Noua varsta se va citi si ea tot de la tastatura, in textbox-
ul corespunzator de pe Form2.
Prin apasare butonului Update ZI se urmareste trecerea tuturor studentilor la forma
zi de invatamant. Acest lucru se realizeaza cu ajutorul urmatorului cod sursa asociat
butonului Update ZI:

private void button3_Click(object sender, EventArgs e)
{
textBox1.Text = "";
7
OleDbConnection Conexiune = new OleDbConnection(AccessProvider);
string stringSQL = "UPDATE student SET forma = 'ZI'";
OleDbCommand myCommand = new OleDbCommand(stringSQL, Conexiune);
try
{
Conexiune.Open();
// se executa comanda si se retine numarul de inregistrari
afectate
int n = myCommand.ExecuteNonQuery();
textBox1.Text = textBox1.Text + String.Format("\r\n Au fost
modificate {0} inregistrari", n);
}
catch (Exception er)
{
MessageBox.Show(er.Message);
}
finally
{
Conexiune.Close();
}
}



Adaugarea unei noi inregistrari in tabela se realizeaza prin apasarea butonului Insert,
care are asociat codul de mai jos:

private void button4_Click(object sender, EventArgs e)
{
textBox1.Text = "";
OleDbConnection conexiune = new OleDbConnection(AccessProvider);
OleDbCommand comanda = new OleDbCommand();
comanda.Connection = conexiune;
int codstudent = 99;
string nume1 = "Anonim";
int varsta1 = 0;
int inaltime1 = 0;
8
string cnp1 = "0000000000000";
string sex1 = "M";
string forma1 = "ZI";
try
{
conexiune.Open();
comanda.Transaction = conexiune.BeginTransaction();
comanda.CommandText = "SELECT MAX(cod) from student"; // sau
"SELECT Count(*) from student"
codstudent = Convert.ToInt16(comanda.ExecuteScalar());
comanda.CommandText = "INSERT into student
values(?,?,?,?,?,?,?)";
comanda.Parameters.Add("cod", OleDbType.Integer).Value =
codstudent + 1;
comanda.Parameters.Add("nume", OleDbType.Char, 10).Value =
nume1;
comanda.Parameters.Add("varsta", OleDbType.Integer).Value =
varsta1;
comanda.Parameters.Add("inaltime", OleDbType.Integer).Value =
inaltime1;
comanda.Parameters.Add("CNP", OleDbType.Char, 13).Value = cnp1;
comanda.Parameters.Add("sex", OleDbType.Char, 2).Value = sex1;
comanda.Parameters.Add("forma", OleDbType.Char, 10).Value =
forma1;
comanda.ExecuteNonQuery();
comanda.Transaction.Commit();
MessageBox.Show("A fost adaugata o inregistrare noua!");
}
catch (Exception er)
{
MessageBox.Show(er.Message);
comanda.Transaction.Rollback();
}
finally
{
conexiune.Close();
}
}

9

Prin apasarea butonului Creare procedura stocata se construieste o procedura stocata
(query) in baza de date. Codul corespunzator evenimentului Click al acestui buton este cel de
mai jos:

private void button5_Click(object sender, EventArgs e)
{
textBox1.Text = "";
string stringProcedura = "CREATE PROCEDURE StudentiVarsta AS " +
"SELECT * from student WHERE varsta=@varsta";
OleDbConnection Conexiune = new OleDbConnection(AccessProvider);
OleDbCommand myCommand = new OleDbCommand();
myCommand.Connection = Conexiune;
myCommand.CommandType = CommandType.Text;

OleDbDataReader myDataReader;

//daca exista, se sterge procedura stocata
myCommand.CommandText = "DROP PROCEDURE StudentiVarsta";
try
{
Conexiune.Open();
myDataReader = myCommand.ExecuteReader();
myDataReader.Close();
}
catch (Exception er)
{
textBox1.Text = "Eroare 1" + er.Message;
}

// se creaza noua procedura
myCommand.CommandText = stringProcedura;
myCommand.CommandType = CommandType.Text;
try
{
myDataReader = myCommand.ExecuteReader();
myDataReader.Close();
}
catch (Exception er)
{
textBox1.Text = "Eroare 2" + er.Message;
}
Conexiune.Close();
textBox1.Text = "Procedura creata cu succes";
}

10


Apelul acestui query se face prin click pe butonul Apel procedura stocata care are, in
spate, urmatorul cod sursa:
private void button6_Click(object sender, EventArgs e)
{
textBox1.Text = "";
OleDbConnection Conexiune = new OleDbConnection(AccessProvider);
OleDbCommand myCommand = new OleDbCommand();
myCommand.Connection = Conexiune;
myCommand.CommandText = "StudentiVarsta";
myCommand.CommandType = CommandType.StoredProcedure;
OleDbDataReader myDataReader;
try
{
Conexiune.Open();
myCommand.Parameters.Add("@varsta", OleDbType.Integer);
myCommand.Parameters["@varsta"].Value = 22;
myCommand.Parameters["@varsta"].Direction =
ParameterDirection.Input;
myDataReader = myCommand.ExecuteReader();
while (myDataReader.Read())
{
textBox1.Text = textBox1.Text + "\r\n" +
myDataReader["nume"] + " " + myDataReader["varsta"];
}
myDataReader.Close();
}
catch (Exception er)
{
textBox1.Text = "Eroare 2" + er.Message;
}
Conexiune.Close();
}

11


Prin click pe butonul View DataSet se urmareste declararea unui DataSet pentru
vizualizarea unei parti din informatiile din baza de date. Acest lucru se implementeaza prin
urmatorul cod sursa:

private void button7_Click(object sender, EventArgs e)
{
textBox1.Text = "";
OleDbConnection Conexiune = new OleDbConnection(AccessProvider);
OleDbDataAdapter myDataAdapter = new OleDbDataAdapter("SELECT * from
student", Conexiune);
DataSet myDataSet = new DataSet();
myDataAdapter.Fill(myDataSet, "Student");
DataTable table = myDataSet.Tables["Student"];
foreach (DataColumn column in table.Columns)
{
textBox1.Text += column.ColumnName + " " + "\r";
}
textBox1.Text = textBox1.Text + "\n";
foreach (DataRow row in table.Rows)
{
textBox1.Text = textBox1.Text + "\n";
foreach (object field in row.ItemArray)
{
textBox1.Text = textBox1.Text + String.Format("{0,-10}",
field);
}
}
}

12


DataSet este un obiect care poate sa retina mai multe tabele, inclusiv cu relatii intre
ele, la nivelul aplicatiei. Este folosit ca sursa de date pentru DataGrid, DropDownList, etc.
Prin apasarea butonului Update DataSet se urmareste declararea unui DataSet si
efectuarea unui update la o parte din informatiile din baza de date. Respectivul update
presupune setarea varstei tuturor studentilor cu o anumita valoare. Acest lucru se
implementeaza prin urmatorul cod sursa:

private void button8_Click(object sender, EventArgs e)
{
textBox1.Text = "";
OleDbConnection Conexiune = new OleDbConnection(AccessProvider);
OleDbDataAdapter myDataAdapter = new OleDbDataAdapter("SELECT * from
student", Conexiune);
DataSet myDataSet = new DataSet();
myDataAdapter.Fill(myDataSet, "Student");
DataTable table = myDataSet.Tables["Student"];

OleDbCommandBuilder cb = new OleDbCommandBuilder(myDataAdapter);

//fara a utiliza OleDbCommandBuilder, care genereaza automat
comenzile
//update, insert si delete, in functie de modificarile din baza de
date, atunci
//se scriu aceste comenzi si se executa

// string SirUpdate = "UPDATE Student SET Varsta = @varsta";
// OleDbCommand cmd = new OleDbCommand(SirUpdate,Conexiune);
// cmd.Parameters.Add(new
OleDbParameter("@varsta",OleDbType.Integer));
// cmd.Parameters["@varsta"].Value=22;
// cmd.CommandText=SirUpdate;
// myDataAdapter.UpdateCommand=cmd;

13
foreach (DataRow row in myDataSet.Tables["Student"].Rows)
{
row["Varsta"] = 22;
}
myDataAdapter.Update(myDataSet, "Student");
textBox1.Text += "Varstele tuturor studentilor au fost actualizate!";
}



Butonul Filter DataSet presupune declararea unui DataSet in scopul filtrarii
informatiilor din baza de date. Codul asociat evenimentului Click al butonului este:

private void button9_Click(object sender, EventArgs e)
{
textBox1.Text = "";
OleDbConnection Conexiune = new OleDbConnection(AccessProvider);
OleDbDataAdapter myDataAdapter = new OleDbDataAdapter("SELECT * from
student", Conexiune);
DataSet myDataSet = new DataSet();
myDataAdapter.Fill(myDataSet, "Student");
string val = "ZI";
string filter = String.Format("Forma = '{0}'", val);
DataRow[] rows = myDataSet.Tables["Student"].Select(filter, "Forma");
foreach (DataRow row in rows)
{
textBox1.Text = textBox1.Text + row["Nume"] + " " +
row["Forma"] + "\r\n";
}
}

14


Butonul Filter DataView presupune declararea unui DataSet in scopul filtrarii
informatiilor din baza de date, cu ajutoul unui DataView. Codul asociat evenimentului
Click al butonului este:

private void button10_Click(object sender, EventArgs e)
{
textBox1.Text = "";
OleDbConnection Conexiune = new OleDbConnection(AccessProvider);
OleDbDataAdapter myDataAdapter = new OleDbDataAdapter("SELECT * from
student", Conexiune);
DataSet myDataSet = new DataSet();
myDataAdapter.Fill(myDataSet, "Student");
DataView dv = new DataView(myDataSet.Tables["Student"]);
dv.Sort = "Nume";
string val = "ZI";
dv.RowFilter = String.Format("Forma = '{0}'", val);
foreach (DataRowView row in dv)
{
textBox1.Text = textBox1.Text + row["Nume"] + " " +
row["Forma"] + "\r\n";
}
}
15