Documente Academic
Documente Profesional
Documente Cultură
Accesul la date este factorul crucial in toate aplicatiile, iar ADO.NET ofera mijloace
de accesare a datelor in aplicatii. ADO.NET este o arhitectura de date deconectata. Datele
sunt extrase din baza de date si stocate pe calculatorul local. Datele se manipuleaza pe
computerul local, iar conectarea la baza de date se realizeaza doar cand se doreste modificarea
inregistrrilor sau extragerea de noi date. Aceste clase se regasesc in dll-ul System.Data.
Clasa DataTable:
Un obiect de tip DataTable reprezinta date stocate in memorie sub forma de linii si coloane
care pot avea sau nu constrangeri. Un obiect de tip DataTable se populeaza cu alte obiecte de
tip DataColumn si DataRow care contin datele propriu-zise.
Obiectele DataTable nu sunt utile pana cand nu le cream o schema adaugand obiecte
DataColumn si setand constrangeri pe fiecare coloana pentru a mentine integritatea datelor si
a limita cantitatea de date pe care o putem adauga.
Incepem prin a crea un tabel simplu si cateva coloane:
Daca nu avem nicio coloana care sa contina elemente unice ( Unique = false ), putem adauga
o coloana index care sa se incrementeze automat pe masura ce adaugam noi linii in tabel.
Acest lucru se face setand proprietatea AutoIncrement a unei coloane true,
AutoIncrementSeed la valoarea de la care vrem sa se inceapa indexarea si AutoIncrementStep
la valoare cu care sa se incrementeze de fiecare data cand un nou rand este adaugat. Cand se
face trimiterea de date dintr-o baza de date locala unei alte baze de date back-end, coloana
care contine indexurile nu se trimite si noile randuri sunt indexate in continuarea celor
existente, insa la o interogare in care este necesara extragerea de informatii din ambele baze
de date, indexurile comune vor genera o exceptie. Pentru a evita acest lucru, indexarea din
baza de date locala trebuie sa fie negativa, AutoIncrementSeed si AutoIncrementStep sa fie
negative deoarece baza de date principala nu va genera numere negative.
IMEI.AutoIncrement = true;
IMEI.AutoIncrementSeed = 1;
IMEI.AutoIncrementStep = 1;
Un obiect DataRow poate fi creat numai in contextul unui DataTable deoarece trebuie sa se
conformeze constrangerilor de pe fiecare coloana. Metoda Rows dintr-un obiect DataTable
returneaza randurile care din tabel, iar metoda Add adauga un nou rand.
DataRow tel1 = Cellphones.NewRow(); //DataRow se conformeaza regulilor din cell
tel1["IMEI"] = "12345";
tel1["Producator"] = "Samsung";
tel1["Proprietar"] = "Andrei";
Cellphones.Rows.Add(tel1);
//metoda 2 de adaugare a unui rand nou
Cellphones.Rows.Add("12876", "Samsung", "Mihai");//Met Rows returneaza randuri
Clasa DataTable are si cateva metode supraincarcate Load care pot fi folosite pentru a adauga
un nou rand tabelului sau sa faca update unuia deja existent. Pentru a folosi metoda Load este
necesar ca tabelul sa aiba setat Primary key. Sunt cateva optiuni pentru LoadOption:
- OverwriteChanges: Rescrie randul deja existent care are acelasi PK cu cel nou si
modifica statutul randurilor la Unchanged;
- PreserveChanges(default): Rescrie randul deja existent dar nu modifica statutul
acestuia;
- Upsert: Rescrie randul deja existent dar nu-i modifica statutul. Randurile noi vor avea
statut de Added, iar cele cu statut Unchanged vor deveni Modified;
Cellphones.LoadDataRow(new Object[]
{"12876","Motorola","Mihai"}, LoadOption.OverwriteChanges);
//LoadOption controleaza modul in care datele sursa (noi) sunt scrise, iar
overwriteChanges asigura scrierea
//Load este o metoda supraincarcata care poate fi folosita fie pt update, fie pentru
scriere
//daca se modifica primary key atunci nu se inlocuieste, ci se adauga (este necesara
prezenta unei coloane Primary Key in tabel )
Accept changes este folosit pentru lucru cu baza de date principala si atunci cand apelam
metoda, sincronizam baza noastra de date locala cu cea principala.
string s = buffer.ToString();
Console.WriteLine(s);
}
Starea unui obiect de tip DataRow este importanta, este o proprietate a acestuia si se
gaseste in mai multe stari:
Detached Obiectul a fost creat dar nu a fost adaugat niciunui tabel;
Added obiectul a fost creat si adaugat unui tabel;
Unchanged obiectul nu a fost modificat de la ultimul apel al metodei AcceptChanges;
Modified obiectul a fost modificat de la ultimul apel al metodei sus mentionate.
Deleted obiectul a fost sters din tabel.
Un obiect DataTable poate retine pana la 3 versiuni diferite ale unui singur rand: cea
originala, cea curenta si cea propusa. Atunci cand un rand este incarcat pentru prima data in
tabel, acesta este trecut in versiunea curenta (Current), deoarece versiunea originala implica
adaugarea si modificarea in prealabil a randului. Executand metoda BeginEdit, randul va intra
in modul editare si datele modificate vor fi puse in instanta Proposed urmand ca la chemarea
metodei EndEdit datele curente sa fie trecute in instanta Original, iar cele noi sa le suprascrie
pe cele curente. Daca executam din nou editarea randului, atunci procedura nu va mai afecta
starea originala.
Putem observa schimbarile ce se produc asupra acestor stari, prin codul de mai jos. Functia
GetDataRowInfo verifica starile fiecarui rand si le afiseaza:
Console.WriteLine(GetDataRowInfo(tel1, "IMEI"));
Cellphones.AcceptChanges();
Console.WriteLine(GetDataRowInfo(tel1, "IMEI"));
tel1.BeginEdit();
tel1 ["IMEI"] = "54321";
Console.WriteLine(GetDataRowInfo(tel1, "IMEI"));
tel1.EndEdit();
Console.WriteLine(GetDataRowInfo(tel1, "IMEI"));
tel1.BeginEdit();
tel1["IMEI"] = "99999";
Console.WriteLine(GetDataRowInfo(tel1, "IMEI"));
tel1.EndEdit();
Console.WriteLine(GetDataRowInfo(tel1, "IMEI"));
Pentru a copia tabelul integral folosim metoda Copy() din clasa DataTable.
Pentru a copia un rand dintr-un tabel se foloseste metoda ImportRow care copiaza randul
impreuna cu starea originala si cea curenta.
clone.ImportRow(copie.Rows[0]);
EnumerateTable(clone);
clone.AcceptChanges();
clone.Rows[0].BeginEdit();
clone.Rows[0].EndEdit();
Console.WriteLine(GetDataRowInfo(clone.Rows[0], "IMEI"));
namespace Curs
{
class Program
{
static void Main(string[] args)
{
try
{
Cellphones.Columns.Add(P);
Cellphones.Columns.Add(pp);
Console.WriteLine(GetDataRowInfo(tel1, "IMEI"));
Cellphones.AcceptChanges();
Console.WriteLine(GetDataRowInfo(tel1, "IMEI"));
tel1.BeginEdit();
tel1["IMEI"] = "54321";
Console.WriteLine(GetDataRowInfo(tel1, "IMEI"));
tel1.EndEdit();
Console.WriteLine(GetDataRowInfo(tel1, "IMEI"));
tel1.BeginEdit();
tel1["IMEI"] = "99999";
Console.WriteLine(GetDataRowInfo(tel1, "IMEI"));
tel1.EndEdit();
Console.WriteLine(GetDataRowInfo(tel1, "IMEI"));
clone.ImportRow(copie.Rows[0]);
EnumerateTable(clone);
clone.AcceptChanges();
clone.Rows[0].BeginEdit();
clone.Rows[0].EndEdit();
Console.WriteLine(GetDataRowInfo(clone.Rows[0], "IMEI"));
}
catch( Exception e )
{
Console.WriteLine(e.Message);
}
string s = buffer.ToString();
Console.WriteLine(s);
}
DataView
Sortare:
DataView view = new DataView(Cellphones);
view.Sort = "IMEI DESC"; //sortarea randurilor in functie de IMEI (default ascendenta)
foreach( DataRowView row in view )
{
Console.WriteLine(" {0} \t {1} \t {2}", row["IMEI"], row["Proprietar"], row["Producator"]); //
afisarea sortarii
}
Metoda RowStateFilter ofera un filtru care se aplica metodei RowState pe fiecare rand al
tabelului. Acest filtru asigura o metoda usoara de a citi versiuni diferite de randuri de date din
tabel. Folosirea acestei metode implica folosirea valorilor de enumarare din DataViewRwState
care sunt niste flag-uri pe biti asupra carora putem folosi operatorul OR ( | ) pentru a crea
filtre. Flagurile sunt:
- Added : returneaza versiunea curenta a randurilor care au statutul ADDED;
- CurrentRows : similar cu Added;
- Deleted : returneaza versiunea originala a randurilor cu statutul DELETED;
- ModifiedCurrent : returneaza versiunea curenta a randurilor care au statutul
MODIFIED;
- ModifiedOriginal : returneaza versiunea originala a randurilor care au statutul
MODIFIED;
- None : returneaza toate randurile, elimina toate filtrele;
- originalRows : returneaza randurile care au o versiune originala;
- Unchanged : returneaza randurile care au versiunea UNCHANGED;
tel1.BeginEdit();
tel1["IMEI"] = "88888";
Console.WriteLine(GetDataRowInfo(tel1, "IMEI"));
tel1.EndEdit();
Console.WriteLine(GetDataRowInfo(tel1, "IMEI"));
view.RowStateFilter = DataViewRowState.ModifiedCurrent;
EnumerateView(view);
Pentru a exporta o vizualizare a tabelului intr-un tabel propriu-zis, folosim metoda ToTable
din clasa DataView.
DataTable export = view.ToTable("Nume_tabela", true, "Proprietar", "IMEI"); // putem adauga
oricate elemente
EnumerateTable(export);
Cellphones.Columns.Add(pp);
tel1.BeginEdit();
tel1["IMEI"] = "88888";
Console.WriteLine(GetDataRowInfo(tel1, "IMEI"));
tel1.EndEdit();
Console.WriteLine(GetDataRowInfo(tel1, "IMEI"));
view.RowStateFilter = DataViewRowState.ModifiedCurrent;
EnumerateView(view);
DataTable export = view.ToTable("Nume_tabela", true, "Proprietar", "IMEI"); //
+Proprietar putem adauga oricate elemente
EnumerateTable(export);
}
catch( Exception e )
{
Console.WriteLine(e.Message);
}
string s = buffer.ToString();
Console.WriteLine(s);
}
DataSet
DateVanzatori.Relations.Add("Piese_V", dt.Columns["Id"],
Piese.Columns["Id_Vanzator"]); // am adaugat o relatie de tip Primary Key intre cele doua
tabele
Metoda DataRelation pune obiectele de tip DataTable din acelasi obiect DataSet in relatii de
tip PK si join si asigura navigarea usoara intre acestea.
DateVanzatori.Relations.Add("Piese_V", dt.Columns["Id"], Piese.Columns["Id_Vanzator"], true);
// am adaugat o relatie de tip Primary Key intre cele doua tabele
Mai multe obiecte DataSet pot fi combinate intr-unul singur folosing metoda Merge care
poate lucra pe toate tipurile de obiecte continute in clasa.
//cream un obiect de date master
DataSet masterData = new DataSet("Sales");
DataTable people = masterData.Tables.Add("People");
people.Columns.Add("Id", typeof(Guid));
people.Columns.Add("Name", typeof(string));
people.PrimaryKey = new DataColumn[] { people.Columns["Id"] };
people.Rows.Add(Guid.NewGuid(), "Joe");
Console.WriteLine("DataSet`ul initial");
EnumerateTable(masterData.Tables[0]);
Cand folosim metoda Merge este impetuos necesar sa avem setat un PK. In cazul in care
niciun PK nu este setat, comanda Merge va functiona ca si o comanda Append.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
namespace Curs
{
class Program
{
static void Main(string[] args)
{
try
{
DataSet DateVanzatori = new DataSet("DateVanzatori");
DataTable dt = DateVanzatori.Tables.Add("Vanzatori"); // adaugam tabelul Vanzatori
la obiectul DateVanzatori
dt.Columns.Add("Id", typeof(Guid));
dt.Columns.Add("Nume", typeof(string));
dt.Columns.Add("Addresa2", typeof(string));
dt.Columns.Add("Oras", typeof(string));
dt.Columns.Add("Tara", typeof(string));
dt.PrimaryKey = new DataColumn[] { dt.Columns["Id"] }; // setam PK pentru
Vanzatori
}
catch( Exception e )
{
Console.WriteLine(e.Message);
}
}
string s = buffer.ToString();
Console.WriteLine(s);
}