curs dot net

Upload: thesheperd

Post on 17-Jul-2015

560 views

Category:

Documents


3 download

TRANSCRIPT

Visual C# 2.0PhD. Lucian Sasu June 4, 2007

2

Cuprins1 Platforma Microsoft .NET 1.1 Prezentare general . . . . . . . . . . . . a 1.2 Arhitectura platformei Microsoft .NET . 1.3 Componente ale lui .NET Framework . . 1.3.1 Microsoft Intermediate Language 1.3.2 Common Language Specication 1.3.3 Common Language Runtime . . . 1.3.4 Common Type System . . . . . . 1.3.5 Metadata . . . . . . . . . . . . . 1.3.6 Assemblies . . . . . . . . . . . . . 1.3.7 Assembly cache . . . . . . . . . . 1.3.8 Garbage collection . . . . . . . . 1.4 Trsturi ale platformei .NET . . . . . . aa 2 Tipuri predenite, tablouri, string-uri 2.1 Vedere general asupra limbajului C# a 2.2 Tipuri de date . . . . . . . . . . . . . . 2.2.1 Tipuri predenite . . . . . . . . 2.2.2 Tipuri valoare . . . . . . . . . . 2.2.3 Tipul enumerare . . . . . . . . 2.3 Tablouri . . . . . . . . . . . . . . . . . 2.3.1 Tablouri unidimensionale . . . . 2.3.2 Tablouri multidimensionale . . 2.4 Siruri de caractere . . . . . . . . . . . 2.4.1 Expresii regulate . . . . . . . . 3 Clase, instructiuni, spatii de 3.1 Clase vedere general . . a 3.2 Transmiterea de parametri 3.3 Conversii . . . . . . . . . . 3.3.1 Conversii implicite nume . . . . . . . . . . . . . . . . 3 . . . . . . . . . . . . . . . . . . . . . . . . . . 11 11 13 14 14 14 15 16 17 18 19 19 19 23 23 25 25 26 31 37 38 39 42 44 47 47 51 57 57

. . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . .

4 3.3.2 Conversiile implicite ale expresiilor constante 3.3.3 Conversii explicite . . . . . . . . . . . . . . 3.3.4 Boxing i unboxing . . . . . . . . . . . . . . s Declaratii de variabile i constante . . . . . . . . . . s Instructiuni C# . . . . . . . . . . . . . . . . . . . . 3.5.1 Declaratii de etichete . . . . . . . . . . . . . 3.5.2 Instructiuni de selectie . . . . . . . . . . . . 3.5.3 Instructiuni de ciclare . . . . . . . . . . . . 3.5.4 Instructiuni de salt . . . . . . . . . . . . . . 3.5.5 Instructiunile try, throw, catch, nally . . . 3.5.6 Instructiunile checked i unchecked . . . . . s 3.5.7 Instructiunea lock . . . . . . . . . . . . . . . 3.5.8 Instructiunea using . . . . . . . . . . . . . . Spatii de nume . . . . . . . . . . . . . . . . . . . . 3.6.1 Declaratii de spatii de nume . . . . . . . . . 3.6.2 Directiva using . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

CUPRINS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 59 62 64 64 64 65 66 68 69 69 69 69 70 71 72 77 77 78 79 79 79 80 80 81 81 82 83 83 83 89 95 95 97 98 99 101

3.4 3.5

3.6

4 Clase 4.1 Declararea unei clase . . . . . . . 4.2 Membrii unei clase . . . . . . . . 4.3 Cmpuri . . . . . . . . . . . . . . a 4.3.1 Cmpuri instante . . . . . a 4.3.2 Cmpuri statice . . . . . . a 4.3.3 Cmpuri readonly . . . . . a 4.3.4 Cmpuri volatile . . . . . a 4.3.5 Initializarea cmpurilor . . a 4.4 Constante . . . . . . . . . . . . . 4.5 Metode . . . . . . . . . . . . . . . 4.5.1 Metode statice i nestatice s 4.5.2 Metode externe . . . . . . 4.6 Proprieti . . . . . . . . . . . . . at 4.7 Indexatori . . . . . . . . . . . . . 4.8 Operatori . . . . . . . . . . . . . 4.8.1 Operatori unari . . . . . . 4.8.2 Operatori binari . . . . . . 4.8.3 Operatori de conversie . . 4.8.4 Exemplu: clasa Fraction . 4.9 Constructori de instant . . . . . a

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

CUPRINS 5 Clase (2). Motenire, polimorsm s 5.1 Constructor static . . . . . . . . . . . . . . . . . . . . 5.2 Clase interioare . . . . . . . . . . . . . . . . . . . . . 5.3 Destructori . . . . . . . . . . . . . . . . . . . . . . . 5.4 Clase statice . . . . . . . . . . . . . . . . . . . . . . . 5.5 Specializarea i generalizarea . . . . . . . . . . . . . . s 5.5.1 Specicarea motenirii . . . . . . . . . . . . . s 5.5.2 Apelul constructorilor din clasa de baz . . . a 5.5.3 Operatorii is i as . . . . . . . . . . . . . . . s 5.6 Clase sealed . . . . . . . . . . . . . . . . . . . . . . . 5.7 Polimorsmul . . . . . . . . . . . . . . . . . . . . . . 5.7.1 Polimorsmul parametric . . . . . . . . . . . . 5.7.2 Polimorsmul adhoc . . . . . . . . . . . . . . 5.7.3 Polimorsmul de motenire . . . . . . . . . . . s 5.7.4 Virtual i override . . . . . . . . . . . . . . . s 5.7.5 Modicatorul new pentru metode . . . . . . . 5.7.6 Metode sealed . . . . . . . . . . . . . . . . . . 5.7.7 Exemplu folosind virtual, new, override, sealed 5.8 Clase i metode abstracte . . . . . . . . . . . . . . . s 5.9 Tipuri partiale . . . . . . . . . . . . . . . . . . . . . .

5 103 . 103 . 104 . 107 . 109 . 111 . 111 . 112 . 113 . 114 . 114 . 115 . 115 . 115 . 117 . 118 . 120 . 121 . 123 . 124 127 . 127 . 131 . 131 . 138 . 138 . 139 . 143 . 143 147 . 147 . 149 . 150 . 150 . 156 . 157 . 157 . 158

. . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . .

6 Structuri. Interfete. Delegati 6.1 Structuri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.1 Structuri sau clase? . . . . . . . . . . . . . . . . . . . 6.2 Interfete . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2.1 Clase abstracte sau interfete? . . . . . . . . . . . . . 6.3 Tipul delegat . . . . . . . . . . . . . . . . . . . . . . . . . . 6.3.1 Utilizarea delegatilor pentru a specica metode la run time . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.3.2 Delegati statici . . . . . . . . . . . . . . . . . . . . . 6.3.3 Multicasting . . . . . . . . . . . . . . . . . . . . . . . 7 Metode anonime. Evenimente. Exceptii. 7.1 Metode anonime . . . . . . . . . . . . . 7.2 Evenimente . . . . . . . . . . . . . . . . 7.2.1 Publicarea i subscrierea . . . . . s 7.2.2 Evenimente i delegati . . . . . . s 7.2.3 Comentarii . . . . . . . . . . . . 7.3 Tratarea exceptiilor . . . . . . . . . . . . 7.3.1 Tipul Exception . . . . . . . . . . 7.3.2 Aruncarea i prinderea exceptiilor s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6 7.3.3 7.3.4 7.3.5

CUPRINS Re ncercarea codului . . . . . . . . . . . . . . . . . . . 169 Compararea tehnicilor de manipulare a erorilor . . . . 171 Sugestie pentru lucrul cu exceptiile . . . . . . . . . . . 172 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 . 173 . 176 . 177 . 178 . 179 . 179 . 182 . 186 . 187 . 188 . 189 . 190 . 191 . 191 . 191

8 Colectii. Clase generice. 8.1 Colectii . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.1.1 Iteratori pentru colectii . . . . . . . . . . . . . . . 8.1.2 Colectii de tip list . . . . . . . . . . . . . . . . . a 8.1.3 Colectii de tip dictionar . . . . . . . . . . . . . . 8.2 Crearea unei colectii . . . . . . . . . . . . . . . . . . . . 8.2.1 Colectie iterabil (stil vechi) . . . . . . . . . . . . a 8.2.2 Colectie iterabil (stil nou) . . . . . . . . . . . . . a 8.3 Clase generice . . . . . . . . . . . . . . . . . . . . . . . . 8.3.1 Metode generice . . . . . . . . . . . . . . . . . . . 8.3.2 Tipuri generice . . . . . . . . . . . . . . . . . . . 8.3.3 Constrngeri asupra parametrilor de genericitate . a 8.3.4 Interfete i delegati generici . . . . . . . . . . . . s 8.4 Colectii generice . . . . . . . . . . . . . . . . . . . . . . . 8.4.1 Probleme cu colectiile de obiecte . . . . . . . . . 8.4.2 Colectii generice . . . . . . . . . . . . . . . . . . .

9 ADO.NET 193 9.1 Ce reprezint ADO.NET? . . . . . . . . . . . . . . . . . . . . 193 a 9.2 Furnizori de date ADO.NET . . . . . . . . . . . . . . . . . 194 n 9.3 Componentele unui furnizor de date . . . . . . . . . . . . . . . 194 9.3.1 Clasele Connection . . . . . . . . . . . . . . . . . . . . 195 9.3.2 Clasele Command . . . . . . . . . . . . . . . . . . . . . 196 9.3.3 Clasele DataReader . . . . . . . . . . . . . . . . . . . . 196 9.3.4 Clasele DataAdapter . . . . . . . . . . . . . . . . . . . 196 9.3.5 Clasa DataSet . . . . . . . . . . . . . . . . . . . . . . . 196 9.4 Obiecte Connection . . . . . . . . . . . . . . . . . . . . . . . . 196 9.4.1 Proprieti . . . . . . . . . . . . . . . . . . . . . . . . . 197 at 9.4.2 Metode . . . . . . . . . . . . . . . . . . . . . . . . . . 199 9.4.3 Evenimente . . . . . . . . . . . . . . . . . . . . . . . . 199 9.4.4 Stocarea stringului de conexiune ier de congurare 199 n s 9.4.5 Gruparea conexiunilor . . . . . . . . . . . . . . . . . . 201 9.4.6 Mod de lucru cu conexiunile . . . . . . . . . . . . . . . 201 9.5 Obiecte Command . . . . . . . . . . . . . . . . . . . . . . . . 202 9.5.1 Proprieti . . . . . . . . . . . . . . . . . . . . . . . . . 202 at 9.5.2 Metode . . . . . . . . . . . . . . . . . . . . . . . . . . 203 9.5.3 Utilizarea unei comenzi cu o procedur stocat . . . . . 206 a a

CUPRINS 9.5.4 Folosirea comenzilor parametrizate . . . . . . . . . . Obiecte DataReader . . . . . . . . . . . . . . . . . . . . . . 9.6.1 Proprieti . . . . . . . . . . . . . . . . . . . . . . . . at 9.6.2 Metode . . . . . . . . . . . . . . . . . . . . . . . . . 9.6.3 Crearea i utilizarea unui DataReader . . . . . . . . . s 9.6.4 Utilizarea de seturi de date multiple . . . . . . . . . . 9.6.5 Accesarea datelor ntro manier sigur din punct de a a vedere a tipului . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . baza . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . de date . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

7 206 208 208 209 209 211

9.6

. 211 213 . 213 . 214 . 215 . 215 . 216 . 216 . 219 . 219 . 220 . 221 . 223 . 225 . 227 229 . 230 . 230 . 232 . 233 . 234 . 234 . 235 . 235 . 235 . 237 . 237 . 239 . 239 . 240 . 240 . 241

10 ADO.NET (2) 10.1 Obiecte DataAdapter . . . . . . . . . 10.1.1 Metode . . . . . . . . . . . . 10.1.2 Proprieti . . . . . . . . . . . at 10.2 Clasa DataSet . . . . . . . . . . . . . 10.2.1 Continut . . . . . . . . . . . . 10.2.2 Clasa DataTable . . . . . . . 10.2.3 Relatii ntre tabele . . . . . . 10.2.4 Popularea unui DataSet . . . 10.2.5 Clasa DataTableReader . . . . 10.2.6 Propagarea modicrilor ctre a a 10.3 Tranzactii ADO.NET . . . . . . . n 10.4 Lucrul generic cu furnizori de date . 10.5 Tipuri nulabile . . . . . . . . . . . .

11 ASP.NET 11.1 Anatomia unei pagini ASP.NET . . . . . . . . . . . . . . . 11.1.1 Adugarea unui control Web . . . . . . . . . . . . . a 11.1.2 Adugarea scriptului inline . . . . . . . . . . . . . a 11.1.3 Code-behind . . . . . . . . . . . . . . . . . . . . . . 11.2 Clasa Page . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.1 Evenimentul Init . . . . . . . . . . . . . . . . . . . 11.2.2 Evenimentul Load . . . . . . . . . . . . . . . . . . 11.2.3 Evenimentul Unload . . . . . . . . . . . . . . . . . 11.3 Crearea unei pagini ASP.NET folosind Visual Studio.NET 11.4 Controale server . . . . . . . . . . . . . . . . . . . . . . . . 11.4.1 Postback . . . . . . . . . . . . . . . . . . . . . . . . 11.4.2 Data Binding . . . . . . . . . . . . . . . . . . . . . 11.5 Controale Web . . . . . . . . . . . . . . . . . . . . . . . . 11.5.1 Label . . . . . . . . . . . . . . . . . . . . . . . . . . 11.5.2 Button . . . . . . . . . . . . . . . . . . . . . . . . . 11.5.3 LinkButton . . . . . . . . . . . . . . . . . . . . . .

8 11.5.4 TextBox . . . . . . . . . . . . . . . . 11.5.5 CheckBox . . . . . . . . . . . . . . . 11.5.6 RadioButton . . . . . . . . . . . . . 11.5.7 DropDownList . . . . . . . . . . . . 11.6 Controale de validare . . . . . . . . . . . . . 11.6.1 RequiredFieldValidator . . . . . . . . 11.6.2 RegularExpressionValidator . . . . . 11.6.3 RangeValidator . . . . . . . . . . . . 11.6.4 CompareValidator . . . . . . . . . . 11.6.5 CustomValidator . . . . . . . . . . . 11.6.6 ValidationSummary . . . . . . . . . . 11.7 Comunicarea cu browserul . . . . . . . . . . 11.7.1 Generarea programatic continutului a 11.7.2 Redirectarea . . . . . . . . . . . . . . 11.8 Cookies . . . . . . . . . . . . . . . . . . . . 11.9 Fiierul de congurare al aplicatiei Web . . . s 11.10Fiierul global.asax . . . . . . . . . . . . . . s 11.11Managementul sesiunii . . . . . . . . . . . . 11.12ViewState . . . . . . . . . . . . . . . . . . . 11.13Application . . . . . . . . . . . . . . . . . . 11.14Alte puncte de interes aplicatii ASP.NET n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

CUPRINS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 241 241 241 242 242 243 243 243 243 245 245 245 246 246 247 248 249 249 250 250

12 Atribute. Fire de executie 12.1 Atribute . . . . . . . . . . . . . . . . . . . . . . 12.1.1 Generaliti . . . . . . . . . . . . . . . . at 12.1.2 Atribute predenite . . . . . . . . . . . . 12.1.3 Exemplicarea altor atribute predenite 12.1.4 Atribute denite de utilizator . . . . . . 12.2 Fire de executie . . . . . . . . . . . . . . . . . . 12.3 Managementul threadurilor . . . . . . . . . . . 12.3.1 Pornirea threadurilor . . . . . . . . . . 12.3.2 Metoda Join() . . . . . . . . . . . . . . 12.3.3 Suspendarea relor de executie . . . . . 12.3.4 Omorrea threadurilor . . . . . . . . . a 12.3.5 Sugerarea prioritilor relor de executie at 12.3.6 Fire fundal i re prim-plan . . . . n s n 12.4 Sincronizarea . . . . . . . . . . . . . . . . . . . 12.4.1 Clasa Interlocked . . . . . . . . . . . . . 12.4.2 Instructiunea lock . . . . . . . . . . . . . 12.4.3 Clasa Monitor . . . . . . . . . . . . . . .

253 . 253 . 253 . 255 . 257 . 260 . 263 . 263 . 263 . 266 . 266 . 267 . 270 . 271 . 272 . 275 . 276 . 277

CUPRINS 13 Servicii Web 13.1 Generaliti . . . . . . . . . . . . . . . . . . . . at 13.1.1 Componentele unui WS . . . . . . . . . 13.2 Discutii asupra blocurilor componente . . . . . . 13.2.1 Protocolul de transport . . . . . . . . . . 13.2.2 Schema de codicare . . . . . . . . . . . 13.2.3 Conventia de formatare . . . . . . . . . . 13.2.4 Mecanismul de descriere . . . . . . . . . 13.2.5 Mecanisme de descoperire . . . . . . . . 13.3 Crearea unui serviciu Web simplu . . . . . . . . 13.3.1 Adunarea a dou numere . . . . . . . . . a 13.3.2 Validarea unui numr de card de credit . a 13.3.3 SW pentru transmitere de continut binar 13.4 SOAP . . . . . . . . . . . . . . . . . . . . . . . 13.4.1 Header-e . . . . . . . . . . . . . . . . . . 13.4.2 Elementul body . . . . . . . . . . . . . .

9 281 . 281 . 281 . 282 . 282 . 282 . 283 . 284 . 284 . 285 . 285 . 286 . 287 . 288 . 289 . 290

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

14 Fluxuri 293 14.1 Sistemul de iere . . . . . . . . . . . . . . . . . . . . . . . . . 293 s 14.1.1 Lucrul cu directoarele: clasele Directory i DirectoryInfo 294 s 14.1.2 Lucrul cu ierele: clasele FileInfo i File . . . . . . . . 296 s s 14.2 Citirea i scrierea datelor . . . . . . . . . . . . . . . . . . . . . 301 s 14.2.1 Clasa Stream . . . . . . . . . . . . . . . . . . . . . . . 301 14.2.2 Clasa FileStream . . . . . . . . . . . . . . . . . . . . . 303 14.2.3 Clasa MemoryStream . . . . . . . . . . . . . . . . . . . 303 14.2.4 Clasa BueredStream . . . . . . . . . . . . . . . . . . . 304 14.2.5 Clasele BinaryReader i BinaryWriter . . . . . . . . . 305 s 14.2.6 Clasele TextReader, TextWriter i descendentele lor . . 306 s 14.3 Operare sincron i asincron . . . . . . . . . . . . . . . . . . 308 as a 14.4 Streamuri Web . . . . . . . . . . . . . . . . . . . . . . . . . . 311 14.5 Serializarea . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311 14.5.1 Crearea unui obiect serializabil . . . . . . . . . . . . . 311 14.5.2 Serializarea . . . . . . . . . . . . . . . . . . . . . . . . 312 14.5.3 Deserializarea unui obiect . . . . . . . . . . . . . . . . 312 14.5.4 Date tranziente . . . . . . . . . . . . . . . . . . . . . . 313 14.5.5 Operatii la deserializare . . . . . . . . . . . . . . . . . 313 Bibliograe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315

10

CUPRINS

Curs 1 Platforma Microsoft .NET1.1 Prezentare general a

Platforma .NET 3.0 este un cadru de dezvoltare a softului, sub care se vor realiza, distribui si rula aplicatiile de tip forme Windows, aplicatii WEB si servicii WEB. Ea const trei prti principale: Common Language Runa n a time, clasele specice platformei i ASP.NET. O infrastructur ajuttoare, s a a Microsoft .NET Compact Framework este un set de interfete de programare care permite dezvoltatorilor realizarea de aplicatii pentru dispozitive mobile precum telefoane inteligente i PDA-uri1 . s .NET Framework constituie un nivel de abstractizare ntre aplicatie i s nucleulul sistemului de operare (sau alte programe), pentru a asigura portabilitatea codului; de asemenea integreaz tehnologii care au fost lansate de a catre Microsoft incepnd cu mijlocul anilor 90 (COM, DCOM, ActiveX, etc) a sau tehnologii actuale (servicii Web, XML). Platforma const cteva grupe de produse: a n a 1. Unelte de dezvoltare - un set de limbaje (C#, Visual Basic .NET, J#, Managed C++, JScript.NET, Objective-C, Python, Smalltalk, Eiel, Perl, Fortran, Cobol, Lisp, Haskell, Pascal, RPG, etc), un set de medii de dezvoltare (Visual Studio .NET, Visio), infrastructura .NET Framework, o bibliotec cuprinztoare de clase pentru crearea serviciilor Web a a 2 (Web Services) , aplicatiilor Web (Web Forms) i aplicatiilor Windows s (Windows Forms). 2. Servere specializate - un set de servere Enterprise .NET: SQL Server 2005, Exchange 2005, BizTalk Server 2006, etc, care pun la dispozitie 1 2

Denitia ocial Microsoft, martie 2005, www.microsoft.com/net/basics/glossary.asp a Serviciilor Web - aplicatii care ofer servicii folosind Web-ul ca modalitate de acces. a

11

12

CURS 1. PLATFORMA MICROSOFT .NET functionaliti diverse pentru stocarea bazelor de date, email, aplicatii at 3 B2B . 3. Servicii Web - cel mai notabil exemplu este .NET Passport - un mod prin care utilizatorii se pot autentica pe site-urile Web vizitate, folosind un singur nume i o parol pentru toate. Dei nu este omiprezent, multe s a s site-uri folosesc pentru a uura accesul utilizatorilor. Alt exempklu l s este MapPoint care permite vizualizarea, editarea si integrarea hartilor. 4. Dispozitive - noi dispozitive nonPC, programabile prin .NET Compact Framework, o versiune redus a lui .NET Framework: Pocket PC Phone a Edition, Smartphone, Tablet PC, Smart Display, XBox, set-top boxes, etc.

Motivul pentru care Microsoft a trecut la dezvoltarea acestei platforme este maturizarea industriei software, accentunduse urmtoarele directii: a a 1. Aplicatiile distribuite - sunt din ce ce mai numeroase aplicatiile de n tip client / server sau cele pe mai multe nivele (ntier). Tehnologiile distribuite actuale cer de multe ori o mare anitate fat de productor a a i prezint o carent acut a interoperrii cu Web-ul. Viziunea actual s a a a a a se deprteaz de cea de tip client/server ctre una care calculatoare, a a a n dispozitive inteligente i servicii conlucreaz pentru atingerea scopurilor s a propuse. Toate acestea se fac deja folosind standarde Internet neproprietare (HTTP, XML, SOAP). 2. Dezvoltarea orientat pe componente - este de mult timp cerut sima a plicarea integrrii componentelor software dezvoltate de diferiti proa ductori. COM (Component Object Model) a realizat acest deziderat, a dar dezvoltarea i distribuirea aplicatiilor COM este prea complex. s a Microsoft .NET pune la dispozitie un mod mai simplu de a dezvolta i s a distribui componente. 3. Modicri ale paradigmei Web - de-a lungul timpului sau adus a mbuntiri tehnologiilor Web pentru a simplica dezvoltarea aplicatiilor. a at ultimii ani, dezvoltarea aplicatiilor Web sa mutat de la prezentare In (HTML i adiacente) ctre capacitate sporit de programare (XML i s a a s SOAP). 4. Alti factori de maturizare a industriei software - reprezint contienti a s zarea cererilor de interoperabilitate, scalabilitate, disponibilitate; unul din dezideratele .NET este de a oferi toate acestea.Bussiness to Bussiness - Comert electronic ntre parteneri de afaceri, diferit de a comertul electronic ntre client i afacere (Bussiness to Consumer B2C). s3

1.2. ARHITECTURA PLATFORMEI MICROSOFT .NET

13

1.2

Arhitectura platformei Microsoft .NET

Figura 1.1: Arhitectura .NET Figura 1.1 schematizeaz arhitectura platformei Microsoft .NET. Orice a program scris ntr-unul din limbajele .NET este compilat Microsoft Intern mediate Language (MSIL), concordant cu Common Language Specican a tion (CLS). Aceste limbaje sunt sprijinite de o bogat colectie de biblioteci a de clase, ce pun la dispozitie faciliti pentru dezvoltarea de Web Forms, at Windows Forms i Web Services. Comunicarea dintre aplicatii i servicii se s s face pe baza unor clase de manipulare XML i a datelor, ceea ce sprijin s a dezvoltarea aplicatiilor cu arhitectur n-tier. Base Class Library exist pen a a tru a asigura functionalitate de nivel sczut, precum operatii de I/O, re de a executie, lucrul cu iruri de caractere, comunicatie prin retea, etc. Aceste s clase sunt reunite sub numele de .NET Framework Class Library, ce permite dezvoltarea rapid a aplicatiilor. La baza tuturor se a cea mai impora a tant component a lui .NET Framework - Common Language Runtime, a a care rspunde de executia ecrui program. Mediile de dezvoltare Visual a a Studio .NET nu sunt absolut necesare pentru a dezvolta aplicatii, dar da torit uneltelor integrate de care dispune sunt cele mai bine adaptate pentru a

14

CURS 1. PLATFORMA MICROSOFT .NET

crearea aplicatiilor. Evident, nivelul inferior este rezervat sistemului de op erare. Trebuie spus c platforma .NET nu este exclusiv dezvoltat pentru a a sistemul de operare Microsoft Windows, ci i pentru arome de Unix (FreeBSD s sau Linux - a se vedea proiectul Mono4 ).

1.31.3.1

Componente ale lui .NET FrameworkMicrosoft Intermediate Language

Una din uneltele de care dispune ingineria software este abstractizarea. Deseori vrem s ferim utilizatorul de detalii, s punem la dispozitia altora a a o interfat simpl, care s permit atingerea scopului, fr a necesare a a a a aa cunoaterea tuturor detaliilor. Dac interfata rmne neschimbat, se pot s a a a a modica toate detaliile interne, fr a afecta actiunile celorlati beneciari ai aa codului. cazul limbajelor de programare, s-a ajuns treptat la crearea unor nivele In de abstractizare a codului rezultat la compilare, precum p-code (cel produs de compilatorul Pascal-P) i bytecode (binecunoscut celor care au lucrat Java). s n Bytecode-ul Java, generat prin compilarea unui ier surs, este cod scris s a ntrun limbaj intermediar care suport POO. Bytecod-ul este acelai timp o a n s abstractizare care permite executarea codului Java, indiferent de platforma int, atta timp ct aceast platform are implementat o main virtual t a a a a a a s a a Java, capabil s traduc mai departe ierul class cod nativ. a a a s n Microsoft a realizat i el propria sa abstractizare de limbaj, aceasta nus mindu-se Common Intermediate Language. Dei exist mai multe limbaje s a de programare de nivel nalt (C#, Managed C++, Visual Basic .NET, etc), la compilare toate vor produce cod acelai limbaj intermediar: Microsoft n s Intermediate Language (MSIL, sau IL pe scurt). Asemntor cu bytecod-ul, a a IL are trsturi OO, precum abstractizarea datelor, motenirea, polimorsaa s mul, sau concepte care s-au dovedit a extrem de necesare, precum exceptiile sau evenimentele. De remarcat c aceast abstractizare de limbaj permite a a rularea aplicatiilor independent de platform (cu aceeai conditie ca la Java: a s s existe o main virtual pentru acea platform). a s a a a

1.3.2

Common Language Specication

Unul din scopurile .NET este de a sprijini integrarea limbajelor astfel at nc programele, dei scrise diferite limbaje, pot interopera, folosind din plin s n motenirea, polimorsmul, s ncapsularea, exceptiile, etc. Dar limbajele nu 4

www.go-mono.com

1.3. COMPONENTE ALE LUI .NET FRAMEWORK

15

sunt identice: unele suport supra arcarea operatorilor (Managed C++, a nc C#), altele nu (Visual Basic .NET); unele sunt case sensitive, altele nu. Pentru a se asigua totui interoperabilitatea codului scris diferite limbaje, s n Microsoft a publicat Common Language Specication (CLS), un subset al lui CTS (Common Type System, vezi 1.3.4), continnd specicatii de reguli a necesare pentru integrarea limbajelor. CLS denete un set de reguli pentru compilatoarele .NET, asigurnd s a faptul c ecare compilator va genera cod care interfereaz cu platforma a a (mai exact, cu CLRul vezi mai jos) ntr-un mod independent de limbajul surs. Obiectele i tipurile create diferite limbaje pot interactiona fr a s n aa probleme suplimentare. Combinatia CTS/CLS realizeaz de fapt interoper a area limbajelor. Concret, se poate ca o clas scris C# s e motenit a a n a s a de o clas scris Visual Basic care arunc exceptii ce sunt prinse de cod a a n a scris C++ sau J#. n

1.3.3

Common Language Runtime

CLR este de departe cea mai important component a lui .NET Framea a work. Este responsabil cu managementul i executia codului scris limbaje a s n .NET, aat format IL; este foarte similar cu Java Virtual Machine. CLR n instantiaz obiectele, face vericri de securitate, depune obiectele mem a a n orie, disponibilizeaz memoria prin garbage collection. a urma compilrii unei aplicatii rezult un ier cu extensia exe, dar In a a s care nu este un executabil portabil Windows, ci un executabil portabil .NET (.NET PE). Acest cod nu este deci un executabil nativ, ci se va rula de ctre CLR, a ntocmai cum un ier class este rulat cadrul JVM. CLR s n folosete tehnologia compilrii JIT - o implementare de main virtual, s a s a a n care o metod sau o functie, momentul care este apelat pentru prima a n n a oar, este tradus cod main. Codul translatat este depus a a n s a ntr-un cache, evitnd-se astfel recompilarea ulterioar. Exist 3 tipuri de compilatoare a a a JIT: 1. Normal JIT - a se vedea descrierea de mai sus. 2. Pre-JIT - compileaz a ntregul cod cod nativ singur dat. mod n a a In normal este folosit la instalri. a 3. Econo-JIT - se foloete pe dispozitive cu resurse limitate. Compileaz s s a codul IL bit cu bit, elibernd resursele folosite de codul nativ ce este a stocat cache. n

16

CURS 1. PLATFORMA MICROSOFT .NET

esent, activitatea unui compilator JIT este destinat a In a a mbunti pera at formanta executiei, ca alternativ la compilarea repetat a aceleiai buci a a s at de cod cazul unor apelri multiple. Unul din avantajele mecanismului JIT n a apare clipa care codul, o dat ce a fost compilat, se execut pe diverse n n a a procesoare; dac maina virtual este bine adaptat la noua platform, atunci a s a a a acest cod va benecia de toate optimizrile posibile, fr a mai nevoie a aa recompilarea lui (precum C++, de exemplu). n

1.3.4

Common Type System

Pentru a asigura interoperabilitatea limbajelor din .NET Framework, o clas scris C# trebuie s e echivalent cu una scris VB.NET, o a a n a a a n interfat scris Managed C++ trebuie s e perfect utilizabil Managed a a n a a n Cobol. Toate limbajele care fac parte din pleiada .NET trebuie s aibe un set a comun de concepte pentru a putea integrate. Modul care acest deziderat n s-a transformat realitate se numete Common Type System (CTS); orice n s limbaj trebuie s recunoasc i s poat manipula nite tipuri comune. a as a a s O scurt descriere a unor faciliti comune (ce vor exhaustiv enumerate a at i tratate cadrul prezentrii limbajului C#): s n a 1. Tipuri valoare - general, CLR-ul (care se ocup de managementul i n a s executia codului IL, vezi mai jos) suport dou tipuri diferite: tipuri a a valoare i tipuri referint. Tipurile valoare reprezint tipuri alocate s a a pe stiv i nu pot avea valoare de null. Tipurile valoare includ tipuas rile primitive, structuri i enumerri. Datorit faptului c de regul s a a a a au dimensiuni mici i sunt alocate pe stiv, se manipuleaza ecient, s a reducnd overhead-ul cerut de mecanismul de garbage collection. a 2. Tipuri referint - se folosesc dac variabilele de un anumit tip cer a a resurse de memorie semnicative. Variabilele de tip referint contin a adrese de memorie heap i pot null. Transferul parametrilor se face s rapid, dar referintele induc un cost suplimentar datorit mecanismului a de garbage collection. 3. Boxing i unboxing - motivul pentru care exist tipuri primitive este s a a orice variabil .NET este acelai ca i Java: performanta. Ins s s n a n compatibil cu clasa Object, rdcina ierarhiei existente .NET. De a a a n exemplu, int este un alias pentru System.Int32, care se deriveaz din a System.ValueType. Tipurile valoare se stocheaz pe stiv, dar pot a a oricnd convertite a ntr-un tip referint memorat heap; acest mecana n ism se numete boxing. De exemplu: s

1.3. COMPONENTE ALE LUI .NET FRAMEWORK int i = 1; //i - un tip valoare object box = i; //box - un obiect referinta

17

Cnd se face boxing, se obtine un obiect care poate gestionat la fel a ca oricare altul, fcnduse abstractie de originea lui. a a Inversa boxing-ului este unboxing-ul, prin care se poate converti un obiect tipul valoare echivalent, ca mai jos: n int j = (int)box; unde operatorul de conversie este sucient pentru a converti de la un obiect la o variabil de tip valoare. a 4. Clase, proprieti, indexatori - platforma .NET suport pe deplin proat a gramarea orientat pe obiecte, concepte legate de obiecte ( a ncapsularea, motenirea, polimorsmul) sau trsturi legate de clase (metode, cms aa a puri, membri statici, vizibilitate, accesibilitate, tipuri interioare, etc). De asemenea se includ trsturi precum proprieti, indexatori, eveniaa at mente. 5. Interfete - reprezint acelai concept precum clasele abstracte din C++ a s (dar continnd doar functii virtuale pure), sau interfetele Java. O a clas care se deriveaz dintr-o interfat trebuie s implementeze toate a a a a metodele acelei interfete. Se permite implementarea simultan a mai a multor interfete ( rest motenirea claselor este simpl). n s a 6. Delegati - inspirati de pointerii la functii din C, ce permit programarea generic. Reprezint versiunea sigur a pointerilor ctre functii din a a a a C/C++ i sunt mecanismul prin care se trateaz evenimentele. s a Exist numeroase componente ale lui CLR care fac cea mai impora l tant parte a lui .NET Framework: metadata, assemblies, assembly cache, a reection, garbage collection.

1.3.5

Metadata

Metadata nseamn general date despre date. cazul .NET, ea a n In reprezint informatii destinate a citite de ctre main, nu de utilizatorul a a s a uman. Este stocat a mpreun cu codul pe care descrie. Pe baza metadatei, a l CLR tie cum s instantieze obiectele, cum s le apeleze metodele, cum s s a a a acceseze proprietile. Printr-un mecanism numit reectare, o aplicatie (nu at

18

CURS 1. PLATFORMA MICROSOFT .NET

neaprat CLR) poate s interogheze aceast metadat i s ae ce expune a a a as a un tip de date (clas, structur, etc). a a Mai pe larg, metadata contine o declaratie a ecrui tip i cte o declaratie a s a pentru ecare metod, cmp, proprietate, eveniment al tipului respectiv. a a Pentru ecare metod implementat, metadata contine informatie care pera a mite arctorului clasei respective s localizeze corpul metodei. De asemena nc a a mai poate contine declaratii despre cultura aplicatiei respective, adic despre a localizarea ei (limba folosit partea de interfat utilizator). a n a

1.3.6

Assemblies

Un assembly reprezint un bloc functional al unei aplicatii .NET. El a formeaz unitatea fundamental de distribuire, versionare, reutilizare i pera a s misiuni de securitate. La runtime, un tip de date exist interiorul unui a n assembly (i nu poate exista exteriorul acestuia). Un assembly contine s n metadate care sunt folosite de ctre CLR. Scopul acestor assemblies este a s se asigure dezvoltarea softului mod plug-and-play. Dar metadatele a n nu sunt suciente pentru acest lucru; mai sunt necesare i manifestele. s Un manifest reprezint metadate despre assembly-ul care gzduiete tia a s purile de date. Contine numele assembly-ului, numrul de versiune, referiri a la alte assemblies, o list a tipurilor assembly, permisiuni de securitate i a n s altele. Un assembly care este artit mp ntre mai multe aplicatii are de asemenea un shared name. Aceast informatie care este unic este optional, neaprnd a a a aa manifestul unui assembly daca acesta nu a fost gndit ca o aplicatie parn a tajat. a Deoarece un assembly contine date care descriu, instalarea lui poate l fcut copiind assemblyul directorul destinatie dorit. Cnd se dorete rua a n a s larea unei aplicatii continute assembly, manifestul va instrui mediul .NET n despre modulele care sunt continute assembly. Sunt folosite de asemenea n i referintele ctre orice assembly extern de care are nevoie aplicatia. s a Versionarea este un aspect deosebit de important pentru a se evita aa s numitul DLL Hell. Scenariile precedente erau de tipul: se instaleaza o aplicatie care aduce nite iere .dll necesare pentru functionare. Ulterior, o s s alt aplicatie care se instaleaz suprascrie aceste iere (sau mcar unul din a a s a ele) cu o versiune mai nou, dar cu care vechea aplicatie nu mai functioneaz a a corespunztor. Reinstalarea vechii aplicatii nu rezolv problema, deoarece a a a doua aplicatie nu va functiona. Dei ierele dll contin informatie relativ s s la versiune interiorul lor, ea nu este folosit de ctre sistemul de operare, n a a ceea ce duce la probleme. O solutie la aceast dilem ar instalarea ierelor a a s dll directorul aplicatiei, dar acest mod ar disprea reutilizarea acestor n n a

1.4. TRASATURI ALE PLATFORMEI .NET biblioteci.

19

1.3.7

Assembly cache

Assembly cache este un director aat mod normal directorul %windir% n n \Assembly. Atunci cnd un assembly este instalat pe o main, el va a s a adugat assembly cache. Dac un assembly este descrcat de pe Internet, a n a a el va stocat assembly cache, n ntr-o zon tranzient. Aplicatiile instalate a a vor avea assemblies ntr-un assembly cache global. acest assembly cache vor exista versiuni multiple ale aceluiai assemIn s bly. Dac programul de instalare este scris corect, va evita suprascrierea a assembly-urilor deja existente (i care functioneaz perfect cu acplicatiile s a instalate), adugnd doar noul assembly. Este un mod de rezolvare a proba a lemei DLL Hell, unde suprascrierea unei biblioteci dinamice cu o variant a mai nou putea duce la nefunctionarea corespunztoare a aplicatiilor antea a rior instalate. CLR este cel care decide, pe baza informatiilor din manifest, care este versiunea corect de assembly de care o aplicatie are nevoie. Acest a mecanism pune capt unei epoci de trist amintire pentru programatori i a a s utilizatori.

1.3.8

Garbage collection

Managementul memoriei este una din sarcinile cele mai consumatoare de resurse umane. Garbage collection este mecanismul care se declaneaz s a atunci cnd alocatorul de memorie rspunde negativ la o cerere de alocare de a a memorie. Implementarea este de tip mark and sweep: se presupune initial c toat memoria alocat se poate disponibiliza, dupa care se determin a a a a care din obiecte sunt referite de variabilele aplicatiei; cele care nu mai sunt referite sunt dealocate, celelalte zone de memorie sunt compactate. Obiectele a cror dimensiune de memorie este mai mare dect un anumit prag nu mai a a sunt mutate, pentru a nu crete semnicativ penalizarea de performant. s a general, CLR este cel care se ocup de apelarea mecanismului de In a garbage collection. Totui, la dorint, programatorul poate cere rularea lui. s a

1.4

Trsturi ale platformei .NET a a

Prin prisma celor prezentate pna acum putem rezuma urmtoarele tra a a sturi: a Dezvoltarea multilimbaj: Deoarece exist mai multe limbaje pentru a aceast platform, este mai uor de implementat prti specice lima a s a n

20

CURS 1. PLATFORMA MICROSOFT .NET bajele cele mai adecvate. Numarul limbajelor curent implementate este mai mare dect 10. Aceast dezvoltare are vedere i debugging-ul a a n s aplicatiilor dezvoltate mai multe limbaje. n Independenta de procesor i de platform: IL este independent s a de procesor. O dat scris i compilat, orice aplicatie .NET (al crei a as a a management este fcut de ctre CLR) poate rulat pe orice platform. a a a a Datorit CLR-ului, aplicatia este izolat de particularitile hardware a a at sau ale sistemului de operare. Managementul automat al memoriei: Problemele de tipul memory leakage nu mai trebuie s preocupe programatorii; overhead-ul ina dus de ctre mecanismul de garbage collection este suportabil, ind a implementat sisteme mult mai timpurii. n Suportul pentru versionare: Ca o lectie aat din perioada de nvt a DLL Hell, versionarea este acum un aspect de care se ine cont. t Dac o aplicatie a fost dezvoltat i testat folosind anumite compoa as a nente, instalarea unei componente de versiune mai nou nu va atenta la a buna functionare a aplicatiei discutie: cele dou versiuni vor coexista n a panic, alegerea lor ind fcut pe baza manifestelor. s a a Sprijinirea standardelor deschise: Nu toate dispozitivele ruleaz a sisteme de operare Microsoft sau folosesc procesoare Intel. Din aceast a cauz orice este strns legat de acestea este evitat. Se folosete XML i a a s s cel mai vizibil descendent al acestuia, SOAP. Deoarece SOAP este un protocol simplu, bazat pe XML, ce folosete ca protocol de transmisie s 5 HTTP , el poate trece uor de rewall-uri, spre deosebire de DCOM s sau CORBA. Distribuirea uoar: Actualmente instalarea unei aplicatii sub Wins a dows nseamn copierea unor iere nite directoare anume, moa s n s dicarea unor valori regitri, instalare de componente COM, etc. n s Dezinstalarea complet a unei aplicatii este in majoritatea cazurilor a o utopie. Aplicatiile .NET, datorit metadatelor i reectrii trec de a s a aceste probleme. Se dorete ca instalarea unei aplicatii s nu s a nsemne mai mult dect copierea ierelor necesare a s ntr-un director, iar dezinstalarea aplicatiei s se fac prin tergerea acelui director. a a s Arhitectur distribuit: Noua losoe este de a asigura accesul la a a servicii Web distribuite; acestea conlucreaz la obtinerea informatiei a 5

Folosit la transmiterea paginilor Web pe Internet

1.4. TRASATURI ALE PLATFORMEI .NET

21

dorite. Platforma .NET asigur suport i unelte pentru realizarea acesa s tui tip de aplicatii. Interoperabilitate cu codul unmanaged: Codul unmanaged se refer la cod care nu se a totalitate sub controlul CLR. El a a n este rulat de CLR, dar nu beneciaz de CTS sau garbage collection. a Este vorba de apelurile functiilor din DLL-uri, folosirea componentelor COM, sau folosirea de ctre o component COM a unei componente a a .NET. Codul existent se poate folosi continuare. n Securitate: Aplicatiile bazate pe componente distribuite cer automat securitate. Modalitatea actual de securizare, bazat pe drepturile a a contului utilizatorului, sau cel din Java, care codul suspectat este n rulat ntr-un sandbox, fr acces la resursele critice este aa nlocuit n .NET de un control mai n, pe baza metadatelor din assembly (zona din care provine - ex. Internet, intranet, maina local, etc) precum i s a s a politicilor de securitate ce se pot seta.

22

CURS 1. PLATFORMA MICROSOFT .NET

Curs 2 Vedere general asupra a limbajului C#. Tipuri predenite. Tablouri. Siruri de caractere2.1 Vedere general asupra limbajului C# a

C#1 este un limbaj de programare modern, simplu, obiectorientat. Este foarte asemntor cu Java i C++, motiv pentru care curba de aare este a a s nvt foarte lin. a Un prim exemplu de program, care contine o serie de elemente ce se vor alni continuare, este: nt n using System; class HelloWorld { public static void Main() { Console.WriteLine(Hello world!); } } Prima linie using System; este o directiv care specic faptul c se vor a a a 2 folosi clasele care sunt incluse spatiul de nume System; un spatiu de n nume este o colectie de tipuri sau o grupare de alte spatii de nume care pot 1 2

# se pronunt sharp a Eng: namespace

23

24

CURS 2. TIPURI PREDEFINITE, TABLOURI, STRING-URI

folosite ntr-un program (detalii vor date mai trziu). cazul de fat, a In a clasa care este folosit din acest spatiu de nume este Console. Mai departe, a orice program este continut ntro clas, cazul nostru HelloWorld. Punctul a n de intrare aplicatie este metoda Main, care nu preia acest exemplu nici n n un argument din linia de comand i nu returneaz explicit un indicator de as a stare a terminrii. a Pentru operatiile de intrareieire cu consola, se folosete clasa Console s s din spatiul de nume System; pentru aceast clas se apeleaz metoda static a a a a WriteLine, care aeaz pe ecran mesajul, dup care face trecerea la linie s a a nou. a O variant uor modicat a programului de mai sus, care se salut a s a n a persoanele ale cror nume este transmis prin linia de comand: a a using System; class HelloWorld { public static void Main( String[] args) { for( int i=0; iFahrenheit."); Console.WriteLine("2. Fahrenheit->Celsius."); Console.Write(":"); string selection = Console.ReadLine(); double f, c = 0; switch (selection) { case "1": Console.Write("Temperatura Celsius: "); f = TemperatureConverter.CelsiusToFahrenheit(Console.ReadLine()); Console.WriteLine("Temperatura in Fahrenheit: {0:F2}", f); break;

5.5. SPECIALIZAREA SI GENERALIZAREA

111

case "2": Console.Write("Temperatura Fahrenheit: "); c = TemperatureConverter.FahrenheitToCelsius(Console.ReadLine()); Console.WriteLine("Temperature in Celsius: {0:F2}", c); break; } } }

5.5

Specializarea i generalizarea s

Specializarea reprezint o tehnic de a obtine noi clase pornind de la cele a a existente. Deseori ntre clasele pe care le modelm putem observa relatii de a genul este un/o: un om este un mamifer, un salariat este un angajat, etc. Toate acestea duc la crearea unei ierarhii de clase, care din clase de baz n a (mamifer sau angajat) descind alte clase, care pe lng comportament din a a clasa de baz mai au i caracteristici proprii. Obtinerea unei clase derivate a s plecnd de la alt clas se numete specializare iar operatia invers se numete a a a s a s generalizare. O clas de baz denete un tip comun, compatibil cu oricare a a s din clasele derivate (direct sau indirect). C# o clas nu trebuie s moteneasc explicit din alt clas; acest In a a s a a a n caz se va considera c ea este implicit derivat din clasa predenit object a a a (tot una cu Object). C# nu permite motenire multipl, eliminnd asts a a fel complicatiile alnite C++. Ca alternativ, se permite totui imple nt n a s mentarea de mai multe interfete.

5.5.1

Specicarea motenirii s

C# se pentru o clas D se denete clasa de baz B folosind urmtoarea In a s a a formul: a class D: B { //declaratii si instructiuni } Dac pentru o anumit clas nu se specic dou puncte urmate de numele a a a a a unei clase de baz atunci object va deveni baz pentru clasa cauz. a a n a Exemplu: //clasa de baza in C#

112

CURS 5. CLASE (2). MOSTENIRE, POLIMORFISM

public class Employee { protected string name; protected string ssn; } //clasa derivata in C# public class Salaried : Employee { protected double salary; public Salaried( string name, string ssn, double salary ) { this.name = name; this.ssn = ssn; this.salary = salary; } } Se observ c cmpurile name i ssn din clasa de baz sunt accesibile clasa a a a s a n derivat, datorit specicatorului de acces protected. a a

5.5.2

Apelul constructorilor din clasa de baz a

exemplul anterior nu sa denit nici un constructor clasa de baz In n a Employee; constructorul clasei derivate trebuie s fac initializrile cmpurilor a a a a conformitate cu parametrii transmii, chiar dac o parte din aceste cmpuri n s a a provin din clasa de baz. Mai logic ar ca clasa de baz s se gseasc un a n a a a a constructor care s initializeze cmpurile proprii: name i ssn. Intruct cona a s a structorii nu se motenesc, e nevoie ca clasa derivat s se fac un apel exs n a a a plicit al constructorului clasei de baz. Acest apel se face prin initializator de a constructor care are forma: dou puncte urmate de base(parametrii-efectivi). a public class Employee { protected string name; protected string ssn; public Employee( string name, string ssn) { this.name = name; this.ssn = ssn; System.Console.WriteLine(Employee constructor: {0}, {1}, name, ssn);

5.5. SPECIALIZAREA SI GENERALIZAREA } } public class Salaried : Employee { protected double salary; public Salaried(string name, string ssn, double salary): base(name, ssn) { this.salary = salary; System.Console.WriteLine(Salaried constructor: {0}, salary); } } class Test { Salaried s = new Salaried(Jesse, 1234567890, 100000.00); } La rulare se va obtine: Employee constructor: Jesse, 1234567890 Salaried constructor: 100000.00

113

de unde se deduce c apelul de constructor de clas de baz se face a a a naintea executrii oricror alte instructiuni continute constructorul clasei derivate. a a n Dac o clas de baz nu are denit nici un constructor, atunci se va a a a crea unul implicit (fr parametri). Dac dup un constructor al unei clase aa a a derivate nu se specic un initializator de constructor, atunci va apelat a constructorul implicit (e creat automat de compilator, e scris de ctre a programator); dac nu exist nici un constructor implicit clasa de baz, a a n a atunci programatorul trebuie s specice un constructor din clasa de baz a a care va apelat, mpreun cu parametrii adecvati. a

5.5.3

Operatorii is i as s

Operatorul is Operatorl is este folosit pentru a verica dac un anumit obiect este a de un anumit tip. Este folosit de obicei nainte operatiilor de downcasting (conversie explicit de la un tip de baz la unul derivat). Operatorul se a a folosete astfel: s

114

CURS 5. CLASE (2). MOSTENIRE, POLIMORFISM

instanta is NumeClasa rezultatul acestei operatii ind true sau false. Exemplu: Employee e = ...; if (e is Salaried) { Salaried s = (Salaried)e; } cazul care sar face conversia explicit iar obiectul nu este de tipul la In n a care se face conversia ar rezulta o exceptie: System.InvalidCastException. Operatorul as Acest operator este folosit pentru conversii explicite, returnnd un obiect a de tipul la care se face conversia sau null dac conversia nu se poate face a (nu se arunc exceptii). Determinarea validitii conversiei se face testnd a at a valoarea rezultat fat de null: dac rezultatul e null atunci conversia nu sa a a a putut face. Ca i precedentul operator se folosete special la downcasting. s s n Exemplu: Employee e = ...; Salaried s = e as Salaried; if (s != null) { //se lucreaza cu instanta valida de tip Salaried }

5.6

Clase sealed

Specicatorul sealed care se poate folosi naintea cuvntului cheie class a specic faptul c clasa curent nu se poate deriva. Este o eroare de compilare a a a ca o clas sealed s e declarat drept clas de baz. a a a a a

5.7

Polimorsmul

Polimorsmul este capacitatea unei entiti de a lua mai multe forme. at limbajul C# polimorsmul este de 3 feluri: parametric, adhoc i de In s motenire. s

5.7. POLIMORFISMUL

115

5.7.1

Polimorsmul parametric

Este cea mai slab form de polimorsm, ind regsit majoritatea a a a a n altor limbaje, ce nu sunt orientate pe obiecte: Pascal, C. Prin polimorsmul parametric se permite ca o implementare de functie s poat prelucra a a orice numr de parametri. Acest lucru se poate obtine prin folosirea unui a parametru de tip params (vezi 3.2).

5.7.2

Polimorsmul adhoc

Se mai numete i supra arcarea metodelor, mecanism prin care s s nc n cadrul unei clase se pot scrie mai multe metode, avnd acelai nume, dar a s tipuri i numere diferite de parametri de apel. Alegerea functiei care va s apelat se va face la compilare, pe baza corespondentei a ntre tipurile de apel i cele formale. s

5.7.3

Polimorsmul de motenire s

Este forma cea mai evoluat de polimorsm. Dac precedentele forme de a a polimorsm sunt aplicabile fr a se pune problema de motenire, acest aa s n caz este necesar s existe o ierarhie de clase. Mecanismul se bazeaz pe faptul a a c o clas de baz denete un tip care este compatibil din punct de vedere a a a s al atribuirii cu orice tip derivat, ca mai jos: class B{...} class D: B{...} class Test { static void Main() { B b = new D();//upcasting=conversie implicita catre baza B } } Intrun astfel de caz se pune problema: ce se ampl cu metodele avnd nt a a aceeai list de parametri formali i care se regsesc cele dou clase? s a s a n a S considerm exemplul urmtor: avem o clas Shape care contine o a a a a metod public void Draw(); din Shape se deriveaz clasa Polygon care implea a menteaz aceeai metod mod specic. Problema care se pune este cum a s a n se rezolv un apel al metodei Draw context de upcasting: a n class Shape

116

CURS 5. CLASE (2). MOSTENIRE, POLIMORFISM

{ public void Draw() { System.Console.WriteLine(Shape.Draw()); } } class Polygon: Shape { public void Draw() { System.Console.WriteLine(Polygon.Draw()); //desenarea s-ar face prin GDI+ } } class Test { static void Main() { Polygon p = new Polygon(); Shape s = p;//upcasting s.Draw(); p.Draw(); } } La compilarea acestui cod se va obtine un avertisment: warning CS0108: The keyword new is required on Polygon.Draw() because it hides inherited member Shape.Draw() dar despre specicatorul new vom vorbi mai jos (oricum, adugarea lui nu a va schimba cu nimic comportamentul de mai jos, doar va duce la disparitia de avertisment). Codul de mai sus va aa: s Shape.Draw() Polygon.Draw() Dac cea dea doua linie aat este conform cu intuitia, primul rezultat a s a a este discutabil, dar justicabil: apelul de metod Draw() este rezolvat a n ecare caz la compilare pe baza tipului declarat al obiectelor; ca atare apelul precedent este legat de corpul metodei Draw din clasa Shape, chiar dac s a a fost instantiat de fapt pe baza unui obiect de tip Polygon.

5.7. POLIMORFISMUL

117

Este posibil ca s se doreasc schimbarea acestui comportament: apelul de a a metod Draw s e rezolvat functie de tipul efectiv al obiectului care face a a n acest apel, i nu de tipul formal declarat. cazul precedent, apelul s.Draw() s In trebuie s se rezolve de fapt ca ind ctre metoda Draw() din Polygon, pentru a a c acesta este tipul la rulare al obiectului s. Cu alte cuvinte, apelul ar trebui a s e rezolvat la rulare i nu la compilare, functie de natura obiectelor. a s n Acest comportament polimorc este referit sub denumirea polimorsm de motenire. s

5.7.4

Virtual i override s

Pentru a asigura faptul c legarea apelului de metode se face la rulare a i nu la compilare, e necesar ca clasa de baz s se specice c metoda s n a a a Draw() este virtual, iar clasa derivat pentru aceeai metod trebuie s a n a s a a se spun c este o suprascriere a celei din baz: a a a class Shape{ public virtual void Draw(){...} } class Polygon{ public override void Draw(){...} } urma executrii metodei Main din clasa de mai sus, se va aa: In a s Polygon.Draw() Polygon.Draw() adic sa apelat metoda corespunztoare tipului efectiv de la rulare, ecare a a n caz. cazul care clasa Polygon este la rndul ei motenit i se dorete In n a s a s s ca polimorsmul s functioneze continuare va trebui ca aceast a treia a n n a clas s suprascrie (override) metoda Draw(). a a Un astfel de comportament polimorc este benec atunci cnd se folosete a s o colectie de obiecte de tipul unei clase de baz: a Shape[] painting = new Shape[10]; painting[0] = new Shape(); painting[1] = new Polygon(); ... foreach( Shape s in painting) s.Draw();

118

CURS 5. CLASE (2). MOSTENIRE, POLIMORFISM

5.7.5

Modicatorul new pentru metode

Modicatorul new se foloeste pentru a indica faptul c o metod dintr-o s a a clas derivat care are aceeai semntur cu una dintro clas de baz nu a a s a a a a este o suprascriere a ei, ci apare ca o nou metod. Este ca i cum metoda a a s declarat new ar avea nume sau parametrii diferiti. a S presupunem urmtorul scenariu: compania A creaz o clas A care a a a a are forma: public class A{ public void M(){ Console.WriteLine(A.M()); } } O alt companie B va crea o clas B care motenete clasa A. Compania a a s s B nu are nici o inuent asupra companiei A sau asupra modului care a n aceasta va face modicri asupra clasei A. Ea va deni interiorul clasei B a n o metod M() i una N(): a s class B: A{ public void M(){ Console.WriteLine(B.M()); N(); base.M(); } protected virtual void N(){ Console.WriteLine(B.N()); } } Atunci cnd compania B compileaz codul, compilatorul C# va produce a a urmtorul avertisment: a warning CS0108: The keyword new is required on B.M() because it hides inherited member A.M() Acest avertisment va notica programatorul c clasa B denete o metod a s a M(), care va ascunde metoda M() din clasa de baz A. Aceast nou metod a a a a ar putea schimba elesul (semantica) lui M(), aa cum a fost creat initial nt s de compania A. Este de dorit astfel de cazuri compilatorul s avertizeze n a despre posibile nepotriviri semantice. Oricum, programatorii din B vor trebui s pun orice caz specicatorul new a a n naintea metodei B.M() pentru a elimina avertismentul. S presupunem c o aplicatie folosete clasa B() felul urmtor: a a s n a

5.7. POLIMORFISMUL class App{ static void Main(){ B b = new B(); b.M(); } } La rulare se va aa: s B.M() B.N() A.M()

119

S presupunem c A decide adugarea unei metode virtuale N() clasa sa, a a a n metod ce va apelat din M(): a a public class A { public void M() { Console.WriteLine(A.M()); N(); } protected virtual void N() { Console.WriteLine(A.N()); } } La o recompilare fcut de B, este dat urmtorul avertisment: a a a warning CS0114: B.N() hides inherited member A.N(). To make the current member override that implementation, add the override keyword. Otherwise, add the new keyword. acest mod compilatorul avertizeaz c ambele clase ofer o metod N() In a a a a a cror semantic poate s difere. Dac B decide c metodele N() nu sunt a a a a a semantic legate cele dou clase, atunci va specica new, informnd compin a a latorul de faptul c versiunea sa este una nou, care nu suprascrie polimorc a a metoda din clasa de baz. a Atunci cnd codul din clasa App este rulat, se va aa la ieire: a s s B.M() B.N() A.M() A.N()

120

CURS 5. CLASE (2). MOSTENIRE, POLIMORFISM

Ultima linie aat se explic tocmai prin faptul c metoda N() din B este s a a a declarat new i nu override (dac ar fost override, ultima linie ar fost a s a B.N(), din cauza polimorsmului). Se poate ca B s decid c metodele M() i N() din cele dou clase sunt a a a s a acest caz, ea poate terge denitia metodei B.M, iar legate semantic. In s pentru a semnala faptul c metoda B.N() suprascrie metoda omonim din a a acest caz, metoda clasa printe, va a nlocui cuvntul new cu override. In a App.Main va produce: A.M() B.N() ultima linie ind explicat de faptul c B.N() suprascrie o metod virtual. a a a a

5.7.6

Metode sealed

O metod de tip override poate declarat ca ind de tip sealed, astfel a a mpiedicnduse suprascrierea ei a ntro clas derivat din cea curent: a a a using System; class A { public virtual void F() { Console.WriteLine(A.F()); } public virtual void G() { Console.WriteLine(A.G()); } } class B: A { sealed override public void F() { Console.WriteLine(B.F()); } override public void G() { Console.WriteLine(B.G()); } }

5.7. POLIMORFISMUL class C: B { override public void G() { Console.WriteLine(C.G()); } }

121

Modicatorul sealed pentru B.F va mpiedica tipul C s suprascrie metoda a F.

5.7.7

Exemplu folosind virtual, new, override, sealed

S presupunem urmtoare ierarhie de clase, reprezentat Fig. 5.1; o a a a n clas X moteneste o clas Y dac sensul sgetii este de la X la Y. Fiecare a s a a a clas are o metod void foo() care determin aarea clasei care este a a a s n denit i pentru care se vor specica new, virtual, override, sealed. S a s aA

+foo(): void

D

B

+foo(): void

+foo(): void

C

+foo(): void

Figura 5.1: Ierarhie de clase presupunem c clasa de test arat astfel: a a public class Test

122

CURS 5. CLASE (2). MOSTENIRE, POLIMORFISM

{ static void Main() { A[] x = new A[4]; x[0] = new A(); x[1] = new B(); x[2] = new C(); x[3] = new D(); A B C D a b c d = = = = new new new new A(); B(); C(); D();

/* secventa 1 */ for(int i=0; i= mc.continut.Length) { return null; } else return mc.continut[index]; } } public bool MoveNext() { index++; return index < mc.continut.Length; } public void Reset() { index = -1; } } } Remarcm c clasa interioar primete prin constructor o referint la obiectul a a a s a de tip colectie, deoarece orice clas interioar C# este automat i static, a a n s a neavnd astfel acces la membrii nestatici ai clasei. a Demonstratia pentru iterarea clasei este: class TestIterator

8.2. CREAREA UNEI COLECTII { static void Main() { MyCollection col = new MyCollection(); foreach(int i in col) { Console.WriteLine(s); } } }

181

Instructiunea foreach va apela initial metoda GetEnumerator pentru a obtine obiectul de iterare i apoi pentru acest obiect se va apela metoda MoveNext s la ecare iteratie. Dac se returneaz true atunci se apeleaz automat i a a a s metoda Current pentru obtinerea elementului curent din colectie; dac se a returneaz false atunci executia lui foreach se termin. a a Implementarea de mai sus permite folosirea simultan a mai multor itera atori, cu pstrarea strii specice. a a Defectele majore ale acestei implementri sunt: a 1. Complexitatea codului (numrul mare de linii). Dei uor de eles i a s s nt s general acceptat (ind de fapt socotit un design pattern), abordarea a presupune scrierea multor linii de cod, motiv pentru care programatorii evita aceasta facilitate, prefernd mecanisme alternative precum a indexatorii. 2. Datorit semnturii metodei Current se returneaz de ecare dat un a a a a Object, pentru care se face e boxing i unboxing (dac in colectie s a avem tip valoare - cazul de mai sus), e downcasting (de la Object la tipul declarat in prima parte a lui foreach, dac in colectie avem tip a primul caz resursele suplimentare de memorie i ciclii proreferint). In a s cesor vor afecta negativ performanta aplicatiei iar in al doilea caz apare o conversie explicit care duneaz performantei globale. Modalitatea a a a de evitare a acestei probleme este ca s nu se implementeze interfetele a IEnumerator i IEnumerable, ci scriind metoda Current astfel inct s s a a returneze direct tipul de date necesar (int in cazul nostru). Acest lucru duce ins la expunerea claselor interioare (vzute ca nite clase auxila a s iare), ceea ce incalc principiul incapsularii. plus, cantitatea de cod a In rmane aceeai. a s Pentru prima problem vom da varianta de mai jos. Pentru cea de a doua, a rezolvarea se d sub forma claselor generice. a

182

CURS 8. COLECTII. CLASE GENERICE.

8.2.2

Colectie iterabil (stil nou) a

Incepand cu C# 2.0 se poate deni un iterator mult mai simplu. Pentru aceasta se foloseste instructiunea yield. yield este folosit a ntr-un bloc de iterare pentru a semnala valoarea ce urmeaz a returnat sau oprirea a a iterrii. Are formele: a yield return expression; yield break; prima form se precizeaz care va valoarea returnat; cea de-a doua In a a a n se precizeaz oprirea iterrii (sfritul secventei de elemente de returnat). a a as Pentru exemplicare, prezentm o metod al crei rezultat este folosit a a a pentru iterare. Valorile returnate de aceast metod sunt ptratele numerelor a a a de la 1 la valoarea argumentului using System; using System.Collections; using System.Text; namespace TestCollection { class Program { static IEnumerable Squares(int number) { for (int i = 1; i Add new item->Application Cona a guration File, implicit acesta avnd numele App.cong. Elementul rdcin a a a a mpreun cu declaratia de XML sunt: a

200

CURS 9. ADO.NET

interiorul elementului rdcin conguration se va introduce elementul In a a a appSettings, care va contine oricte perechi cheie-valoare interiorul unui a n atribut numit add, precum mai jos: Clasele neceasre pentru accesarea ierului de congurare se gsesc spatiul s a n de nume System.Conguration. Pentru a se putea folosi acest spatiu de nume trebuie s se adauge o referint la assembly-ul care contine deaceast a a a clas: din Solutin explorer click dreapta pe proiect->Add reference. . . ->se a alege tab-ul .NET i de acolo System.Conguration. Utilizarea stringului de s conexiune denit anterior se face astfel: using System; using System.Data; using System.Data.SqlClient; using System.Configuration; public class UsingConfigSettings { public static void Main() { SqlConnection con = new SqlConnection( ConfigurationManager.AppSettings["constring"]; //se lucreaza cu conexiunea con.Close(); } } Este posibil ca ntr-o aplicatie s se foloseasc mai multe conexiuni, motiv a a pentru care se sugereaz ca loc de varianta precedent s se foloseasc a n a a a elementul XML : ... Preluarea unui string de conexiune se face prin:

201

string cnStr = ConfigurationManager.ConnectionStrings["SqlProviderPubs"].ConnectionString;

9.4.5

Gruparea conexiunilor

Gruparea conexiunilor2 reprezint reutilizarea resurselor de tip conexia une la o baz de date. Atunci cnd se creeaz o grupare de conexiuni se a a a genereaz automat mai multe obiecte de tip conexiune, acest numr ind a a egal cu minimul setat pentru gruparea respectiv. O nou conexiune este a a creat dac toate conexiunile sunt ocupate i se cere o nou conexiune. Dac a a s a a dimensiunea maxim setat a gruprii este atins, atunci nu se va mai crea a a a o conexiune nou, ci se va pune a ntro coad de ateptare. Dac ateparea a s a s dureaz mai mult dect este precizat valoarea de Timeout se va arunca o a a n exceptie. Pentru a returna o conexiune la grupare trebuie apelat metoda a Close() sau Dispose() pentru acea conexiune. Sursele de date .NET administreaz automat gruparea de conexiuni, dea grevndu-l pe programator de aceast aspect ce nu ine de logica aplicatiei. La a t dorint comportamentul implicit se poate modica prin intemediul continutului a stringului de conectare.

9.4.6

Mod de lucru cu conexiunile

Se cere ca o conexiune s e a ntotdeauna nchis (i dac se poate, ct a s a a mai repede posibil). Ca atare, este de preferat ca s se aplice o schem de a a lucru de tipul: IDBConnection con = ... try { //deschidere conexiune2

Engl: connection pooling

202 //lucru pe baza } catch(Exception e) { //tratare de exceptie } finally { con.Close(); }

CURS 9. ADO.NET

Deoarece se garanteaz ca blocul nally este executat indiferent dac apare a a sau nu o exceptie, cazul de mai sus se va n nchide mod garantat conexin unea.

9.5

Obiecte Command

Un clas de tip Command dat de un furnizor .NET trebuie s implea a a menteze interfata IDbCommand, ca atare toate vor asigura un set de servicii bine specicat. Un asemenea obiect este folosit pentru a executa comenzi pe baza de date: SELECT, INSERT, DELETE, UPDATE sau apel de proceduri stocate (dac SGBD-ul respectiv tie acest lucru). Comanda se poate a s executa numai dac s-a deschis o conexiune la baza de date. a Exemplu: SqlConnection con = new SqlConnection( ConfigurationManager.AppSettings["constring"]; SqlCommand cmd = new SqlCommand("SELECT * FROM Customers", con); Codul care utilizeaz o comand pentru lucrul cu siere mdb sau xls ar a a foarte asemntor, cu diferenta c loc de SqlCommand se folosete OleDa a a n s bCommand, din spatiul de nume System.Data.OleDb. Nu trebuie modicat altceva, doarece locatia sursei de date se specic doar la conexiune. a Se observ c obiectul de conexiune este furnizat comenzii create. Enua a merm mai jos principalele proprieti i metode ale unui obiect de tip coa at s mand. a

9.5.1

Proprieti at

1. CommandText: de tip String, cu ambii accesori; contine comanda SQL sau numele procedurii stocate care se execut pe sursa de date. a

9.5. OBIECTE COMMAND

203

2. CommandTimeout: de tip int, cu ambii accesori; reprezint numrul a a de secunde care trebuie s e ateptat pentru executarea interogrii. a s a Dac se depeste acest timp, atunci se arunc o exceptie. a as a 3. CommandType: de tip CommandType (enumerare), cu ambii accesori; reprezint tipul de comand care se execut pe sursa de date. Valorile a a a pot : CommandType.StoredProcedure - interpreteaz comanda continut a a proprietatea CommandText ca o un apel de procedur stocat n a a denit baza de date. a n CommandType.Text - interpreteaz comanda ca ind o comand a a SQL clasic; este valoarea implicit. a a CommandType.TableDirect - momentan disponibil numai pentru furnizorul OLE DB (deci pentru obiect de tip OleDbCommand); dac proprietatea CommandType are aceast valoare, atunci proa a prietatea CommandText este interpretat ca numele unui tabel a pentru care se aduc toate liniile i coloanele la momentul exes cutrii. a 4. Connection - proprietate de tip System. Data. [.NET Data Provider]. PrexConnection, cu ambii accesori; contine obiectul de tip conexiune folosit pentru legarea la sursa de date; Prex este prexul asociat furnizorului respectiv (a se vedea tabelul 9.1). 5. Parameters - proprietate de tip System.Data.[.NET Data Provider]. PrexParameterCollection, read-only; returneaz o colectie de parametri a care s-au transmis comenzii; aceast list a fost creat prin apelul a a a metodei CreateParameter().Prex reprezint acelasi lucru ca mai sus. a 6. Transaction - proprietate de tip System.Data.[.NET Data Provider]. PrexTransaction, read-write; permite accesul la obiectul de tip tranzactie care se cere a executat pe sursa de date.

9.5.2

Metode

1. Constructori - un obiect de tip comand poate creat i prin intera s mediul apelului de constructor; de exemplu un obiect SqlCommand se poate obtine astfel: SqlCommand cmd; cmd = new SqlCommand();

204

CURS 9. ADO.NET cmd = new SqlCommand(string CommandText); cmd = new SqlCommand(string CommandText, SqlConnection con ); cmd = new SqlCommand(string CommandText, SqlConnection con, SqlTransaction trans);

2. Cancel() - ncearc s opreasc o comand dac ea se a executie. a a a a a a n Dac nu se a executie, sau aceast a a n a ncercare nu are nici un efect nu se intmpl nimic. a a 3. Dispose() - distruge obiectul comand. a 4. ExecuteNonQuery() - execut o comand care nu returneaz un set de a a a date din baza de date; dac comanda a fost de tip INSERT, UPDATE, a DELETE, se returneaz numrul de a a nregistrri afectate. Dac nu este a a denit conexiunea la baza de date sau aveasta nu este deschis, se a a arunc o exceptie de tip InvalidOperationException. a Exemplu: SqlConnection con = new SqlConnection( ConfigurationManager.AppSettings["constring"]); SqlCommand cmd = new SqlCommand(); cmd.CommandText = "DELETE FROM Customers WHERE CustomerID = SEVEN"; cmd.Connection = con; con.Open(); Console.WriteLine(cmd.ExecuteNonQuery().ToString()); con.Close() exemplul de mai sus se returneaz numrul de In a a nregistrri care au a fost terse. s 5. ExecuteReader() - execut comanda continut proprietatea Coma a n mandText i se returneaz un obiect de tip IDataReader (e.g. Sqls a DataReader sau OleDbDataReader ). Exemplu: se obtine continutul tabelei Customers ntrun obiect de tip SqlDataReader (se presupune c baza de date se stocheaz pe un server a a MSSQL): SqlConnection con = new SqlConnection( ConfigurationManager.AppSettings["constring"]); SqlCommand cmd = new SqlCommand(); cmd.CommandText = "SELECT * FROM Customers";

9.5. OBIECTE COMMAND cmd.Connection = con; con.Open(); SqlDataReader reader = cmd.ExecuteReader(); while(reader.Read()) { Console.WriteLine("{0} - {1}", reader.GetString(0), reader.GetString(1)); } reader.Close(); con.Close();

205

Metoda ExecuteReader() mai poate lua un argument optional de tip enumerare CommandBehavior care descrie rezultatele i efectul asupra s bazei de date: CommandBehavior.CloseConnection - conexiunea este nchis atunci a cnd obiectul de tip IDataReader este a nchis. CommandBehavior.KeyInfo - comanda returnez informatie dea spre coloane i cheia primar. s a CommandBehavior.SchemaOnly - comanda returnez doar informatie a despre coloane. CommandBehavior.SequentialAccess - d posibilitatea unui DataReader a s manipuleze a nregistrri care contin cmpuri cu valori binare de a a mare ntindere. Acest mod permite arcarea sub forma unui ux nc de date folosind GetChars() sau GetBytes(). CommandBehavior.SingleResult - se returneaz un singur set de a rezultate CommandBehavior.SingleRow - se returneaz o singur linie. De a a exemplu, dac codul anterior a n nainte de while obtinerea obiec tului reader sar face cu: SqlDataReader reader = cmd.ExecuteReader( CommandBehavior.SingleRow); atunci sar returna doar prima nregistrare din setul de date. 6. ExecuteScalar() - execut comanda continut proprietatea Coma a n mandText; se returneaz valoarea primei coloane de pe primul rnd a a a setului de date rezultat; folosit pentru obtinerea unor rezultate de tip agregat (SELECT COUNT(*) FROM CUSTOMERS, de exemplu).

206

CURS 9. ADO.NET

7. ExecuteXmlReader() - returneaz un obiect de tipul XmlReader obtinut a din rezultatul interogrii pe sursa de date. a Exemplu: SqlCommand custCMD=new SqlCommand("SELECT * FROM Customers FOR XML AUTO, ELEMENTS", con); System.Xml.XmlReader myXR = custCMD.ExecuteXmlReader();

9.5.3

Utilizarea unei comenzi cu o procedur stocat a a

Pentru a se executa pe server o procedur stocat denit baza respeca a a n tiv, este necesar ca obiectul comand s aibe proprietatea CommandType la a a a valoarea CommandType.StoredProcedure iar proprietatea CommandText s a contin numele procedurii stocate: a SqlConnection con = new SqlConnection( ConfigurationManager.AppSettings["constring"]); SqlCommand cmd = new SqlCommand("Ten Most Expensive Products", con); cmd.CommandType = CommandType.StoredProcedure; con.Open(); SqlDataReader reader = cmd.ExecuteReader(); while(reader.Read()) { Console.WriteLine("{0} - {1}", reader.GetString(0), reader.GetDecimal(1)); } reader.Close(); con.Close(); Observatie: se remarc toate exemplele de mai sus faptul c ecare conex a n a iune se nchide manual, printr-un apel de tipul con.Close(). Daca conexiunea a fost folosit pentru un obiect de tip DataRead atunci acesta din urm a a trebuie s e i el a s nchis, naintea nchiderii conexiunii. Dac nu se face acest a apel atunci conexiunea va inut ocupat i nu va putea reutilizat. t a as a

9.5.4

Folosirea comenzilor parametrizate

Exist posibilitatea de a rula cod SQL (interogri, proceduri stocate) a a pe server care s e parametrizate. Orice furnizor de date .NET permite a crearea obiectelor parametru care pot adugate la o colectie de parametri a ai comenzii. Valoarea cestor parametrii se specic e prin numele lor (cazul a ia lor (cazul OleDbParameter ). SqlParameter ), e prin pozit

9.5. OBIECTE COMMAND

207

Exemplu: vom aduce din tabela Customers toate nregistrrile care au a n cmpul Country valoarea USA. a SqlConnection con = new SqlConnection( ConfigurationManager.AppSettings["constring"]); SqlCommand cmd = new SqlCommand("SELECT * FROM Customers WHERE Country=@country",con); SqlParameter param = new SqlParameter("@country", SqlDbType.VarChar); param.Value = "USA"; cmd.Parameters.Add( param ); con.Open(); SqlDataReader reader = cmd.ExecuteReader(); while(reader.Read()) { Console.WriteLine("{0} - {1}", reader.GetString(0), reader.GetString(1)); } reader.Close(); con.Close(); Pentru parametrul creat sa setat tipul lui (ca ind tip SQL ir de caracs tere) i valoarea. De retinut faptul c numele parametrului se prexeaz cu s a a caracterul @. cazul care un parametru este de ieire, acest lucru trebuie spus In n s explicit folosind proprietatea Direction a parametrului respectiv: SqlCommand cmd = new SqlCommand( "SELECT * FROM Customers WHERE Country = @country; " + "SELECT @count = COUNT(*) FROM Customers WHERE Country = @country", con); SqlParameter param = new SqlParameter("@country", SqlDbType.VarChar); param.Value = "USA"; cmd.Parameters.Add( param ); cmd.Parameters.Add(new SqlParameter("@count", SqlDbType.Int)); cmd.Parameters["@count"].Direction = ParameterDirection.Output; con.Open(); SqlDataReader reader = cmd.ExecuteReader(); while(reader.Read()) { Console.WriteLine("{0} - {1}", reader.GetString(0), reader.GetString(1));

208 } reader.Close(); Console.WriteLine("{0} - {1}", "Count", cmd.Parameters["@count"].Value.ToString()); con.Close(); Remarcm urmtoarele: a a

CURS 9. ADO.NET

este posibil ca ntro comand s se execute mai multe interogri a a a pentru parametrul de ieire numit @count trebuie fcut declarare s a a de directie; implicit un parametru este de intrare parametrii de ieire sunt accesibili doar dup s a nchiderea obiectului de tip DataReader

9.6

Obiecte DataReader

Un obiect de tip DataReader este folosit pentru a citi date dintr-o surs a de date. Caracteristicile unei asemenea clase sunt: 1. implementeaz a ntotdeauna interfata IDataReader 2. se lucreaz conectat la sursa de date - pe toat perioada ct este accesat a a a un DataReader necesit conexiune activ a a 3. este de tip read-only; dac se dorete modicarea datelor se poate folosi a s un DataSet + DataAdapter 4. este de tip forward-only - metoda de modicare a pozitiei curente este doar directia n nainte; orice re ntoarcere presupune reluarea nregistrrilor a (dac programatorul nu implementeaz el singur un mecanism de coad) a a a Avantajele utilizrii acestui tip de obiecte sunt: accesul conectat, performantele a bune, consumul mic de resurse i tipizarea puternic. s a

9.6.1

Proprieti at

1. IsClosed - proprietate read-only, returneaz true daca obiectul este a deschis, false altfel 2. HasRows - proprietate boolean read-only care spune dac readerul a a contine cel putin o nregistrare

9.6. OBIECTE DATAREADER 3. Item - indexator care d acces la cmpurile unei a a nregistrri a 4. FieldCount - d numrul de cmpuri din a a a nregistrarea curent a

209

9.6.2

Metode

1. Close() - nchide obiectul de citire i elibereaz resursele client. Este s a obligatoriu apelul acestei metode inaintea nchiderii conexiunii. 2. GetBoolean(), GetByte(), GetChar(), GetDateTime(), GetDecimal(), GetDouble(), GetFloat(), GetInt16(), GetInt32(), GetInt64(), GetValue(), GetString() returneaz valorile cmpurilor din a a nergistrarea curent. a Preiau ca parametru indicele coloanei a crei valoare se cere. Geta Value() returneaz un obiect de tip Object, pentru celelalte tipul retura nat este descris de numele metodelor. 3. GetBytes(), GetChars() - returneaz numrul de octeti / caractere cititi a a dintrun cmp ce stocheaz o structur de dimensiuni mari; primete a a a s ca parametri indicele de coloan (int), pozitia din acea coloan de unde a a se va ncepe citirea, vectorul care se face citirea, pozitia buer de n n la care se depun datele citite, numrul de octeti/caractere ce urmeaz a a a cititi. 4. GetDataTypeName() - returneaz tipul coloanei specicat prin indice a 5. GetName() - returneaz numele coloanei a 6. IsDBNull() - returneaz true dac cmpul specicat prin index este a a n a o valoare de NULL (din baza de date) 7. NextResult() - determin trecerea la urmtorul rezultat, dac aceasta a a a exist; acest caz returneaz true, altfel false (este posibil ca a n a ntr un DataReader s vin mai multe rezultate, provenind din interogri a a a diferite) 8. Read() - determin trecerea la urmtoarea a a nregistrare, dac aceasta exa ista; acest caz ea returneaz true. Metoda trebuie chemat cel putin a n a a o dat, deoarece initial pozitia curent este a a naintea primei nregistrri. a

9.6.3

Crearea i utilizarea unui DataReader s

Nu este posibil s se creeze un obiect de tip DataReader cu ajutorul a unui constructor, ci prin intermediul unui obiect de tip Command, folosind

210

CURS 9. ADO.NET

apelul ExecuteReader() (a se vedea sectiunea 9.3.2). Pentru comanda re spectiv se specic instructiunea care determin returnarea setului de date a a a precum i obiectul de conexiune. Aceast conexiune trebuie s e deschis s a a a naintea apelului ExecuteReader(). Trecerea la urmtoarea a nregistrare se face folosind metoda Read(). Cnd se dorete a s ncetarea lucrului se nchide readerul i conexiunea. Omiterea s nchiderii obiectului de tip reader va duce la imposibilitatea reutilizrii conexiunii initiale. Dup ce se a a nchide acest DataReader este necesar i chiderea explicit a conexiunii (acest lucru nu a s n a mai e mandatoriu doar dac la apelul metodei ExecuteReader sa specicat a CommandBehavior.CloseConnection). Dac se a ncearc refolosirea conexia unii fr ca readerul s fost aa a nchis se va arunca o exceptie InvalidOpera tionException. Exemplu: SqlConnection conn = new SqlConnection ( ConfigurationManager.AppSettings["constring"]); SqlCommand selectCommand = new SqlCommand("select * from ORDERS", conn); conn.Open (); OleDbDataReader reader = selectCommand.ExecuteReader ( ); while ( reader.Read () ) { object id = reader["OrderID"]; object date = reader["OrderDate"]; object freight = reader["Freight"]; Console.WriteLine ( "{0}\t{1}\t\t{2}", id, date, freight ); } reader.Close (); conn.Close (); Este perfect posibil ca un obiect de tip DataReader s aduc datele prin a a apelul unei proceduri stocate (de fapt invocarea acestei proceduri este fcut a a de ctre obiectul de tip Command ). a Urmtoarele observatii trebuie luate considerare atunci cnd se lua n a creaz cu un obiect DataReader : a Metoda Read() trebuie s e a ntotdeauna apelat a naintea oricrui acces a la date; pozitia curent la deschidere este a naintea primei nregistrri. a Intotdeauna apelati metoda Close() pe un DataReader i pe conexiunea s asociat ct mai repede posibil; caz contrar conexiunea nu poate a a n reutilizat a

9.6. OBIECTE DATAREADER

211

Procesarea datelor citite trebuie s se fac dup a a a nchiderea conexiunii; felul acesta conexiunea se las liber pentru a putea reutilizat. n a a a

9.6.4

Utilizarea de seturi de date multiple

Este posibil ca ntrun DataReader s se aduc mai multe seturi de date. a a Acest lucru ar micora numrul de apeluri pentru deschiderea unei conexiuni s a la stratul de date. Obiectul care permite acest lucru este chiar cel de tip Command : string select = "select * from Categories; select * from customers"; SqlCommand command = new SqlCommand ( select, conn ); conn.Open (); SqlDataReader reader = command.ExecuteReader (); Trecerea de la un set de date la altul se face cu metoda NextResult() a obiectului de tip Reader : do { while ( reader.Read () ) { Console.WriteLine ( "{0}\t\t{1}", reader[0], reader[1] ); } }while ( reader.NextResult () );

9.6.5

Accesarea datelor ntro manier sigur din punct a a de vedere a tipului

S considerm urmtoarea secvent de cod: a a a a while ( reader.Read () ) { object id = reader["OrderID"]; object date = reader["OrderDate"]; object freight = reader["Freight"]; Console.WriteLine ( "{0}\t{1}\t\t{2}", id, date, freight ); } Dup cum se observ, este posibil ca valorile cmpurilor dintro a a a nregistrare s e accesate prin intermediul numelui coloanei (sau a indicelui ei, pornind a de la 0). Dezavantajul acestei metode este c tipul datelor returnate este a

212

CURS 9. ADO.NET

pierdut (ind returnate obiecte de tip Object), trebuind fcut un downcasta a ing pentru a utiliza din plin facilitile tipului respectiv. Pentru ca acest at lucru s nu se ample se pot folosi metodele GetXY care returneaz un tip a nt a specic de date: while ( reader.Read () ) { int id = reader.GetInt32 ( 0 ); DateTime date = reader.GetDateTime ( 3 ); decimal freight = reader.GetDecimal ( 7 ); Console.WriteLine ( "{0}\t{1}\t\t{2}", id, date, freight ); } Avantajul secventei anterioare este c dac se a a ncearc aducerea valorii unui a cmp pentru care tipul nu este dat corect se arunc o exceptie InvalidCasa a tException; altfel spus, accesul la date se face sigur din punct de verere al tipului datelor. Pentru a evita folosirea unor constante magice ca indici de coloan a (precum mai sus: 0, 3, 7), se poate folosi urmtoarea strategie: indicii se a obtin folosind apel de metod GetOrdinal la care se specic numele coloanei a a dorite: private int OrderID; private int OrderDate; private int Freight; ... OrderID = reader.GetOrdinal("OrderID"); OrderDate = reader.GetOrdinal("OrderDate"); Freight = reader.GetOrdinal("Freight"); ... reader.GetDecimal ( Freight ); ...

Curs 10 ADO.NET (2)10.1 Obiecte DataAdapter

La fel ca i Connection, Command, DataReader, obiectele de tip DataAdapter s fac parte din furnizorul de date .NET specic ecrui tip de surs de date. a a Scopul ei este s permit umplerea unui obiect DataSet cu date i reectarea a a s schimbrilor efectuate asupra acestuia a napoi baza de date (DataSet pern mite lucrul deconectat de la baza de date). Orice clas de tipul DataAdapter (de ex SqlDataAdapter i OleDbDataAdapter) a s este derivat din clasa DbDataAdapter (clas abstract). Pentru orice obiect a a a de acest tip trebuie specicat minim comanda de tip SELECT care s popa a uleze un obiect de tip DataSet; acest lucru este stabilit prin intermediul proprietii SelectCommand de tip Command (SqlCommand, OleDbCommand, at . . . ). cazul care se dorete i modicarea informatiilor din sursa de date In n s s (inserare, modicare, tergere) trebuie specicate obiecte de tip comand via s a proprietile: InsertCommand, UpdateCommand, DeleteCommand. at Exemplu: mai jos se preiau nregistrrile din 2 tabele: Authors i TitleAua s thor i se trec s ntrun obiect de tip DataSet pentru a procesate ulterior. using System; using System.Data; using System.Data.SqlClient; class DemoDataSource { static void Main() { SqlConnection conn = new SqlConnection( ConfigurationManager.AppSettings["constring"]); 213

214

CURS 10. ADO.NET (2)

SqlDataAdapter daAuthors = new SqlDataAdapter("SELECT au_id, au_fname, au_lname FROM authors",conn); daAuthors.Fill(ds,"Author"); SqlDataAdapter daTitleAuthor = new SqlDataAdapter("SELECT au_id, title_id FROM titleauthor", conn); daTitleAuthor.Fill(ds,"TitleAuthor"); } } Prezentm mai jos cele mai importante componente ale unei clase de tip a DataAdapter.

10.1.1

Metode

1. Constructori de la cei impliciti pn la cei care se specic o comand a a n a a de tip SELECT i conexiunea la sursa de date. Pentru un obiect de s tip SqlDataAdapter se poate crea o instant urmtoarele moduri: a n a SqlDataAdapter da = new SqlDataAdapter(); sau: SqlCommand cmd = new SqlCommand("SELECT * FROM Employees"); SqlDataAdapter da = new SqlDataAdapter(cmd); sau: String strCmd = "SELECT * FROM Employees"; String strConn = "..."; SqlDataAdapter da = new SqlDataAdapter(strCmd, strConn);

2. Fill() metod polimorc, permitnd umplerea unei tabele dintrun a a a obiect de tip DataSet cu date. Permite specicarea obiectului DataSet care se depun datele, eventual a numelui tablei din acest DataSet, n numrul de a nregistrare cu care s se a nceap popularea (prima avnd a a indicele 0) i numrul de s a nregistrri care urmeaz a aduse. Rea a turneaz de ecare dat numrul de a a a nregistrri care au fost aduse din a clipa care se apeleaz Fill() se procedeaz astfel: baz. In a n a a

10.2. CLASA DATASET (a) Se deschide conexiunea (dac ea nu a fost explicit deschis) a a

215

(b) Se aduc datele i se populeaz un obiect de tip DataTable din s a DataSet (c) Se nchide conexiunea (dac ea nu a fost explicit deschis!) a a De remarcat c un DataAdapter si poate deschide i a s nchide singur conexiunea, dar dac aceasta a fost deschis a a naintea metodei Fill() atunci tot programatorul trebuie s o a nchid. a 3. Update() metod polimorc, permitnd reectarea modicrilor efeca a a a tuate ntreun DataSet. Pentru a functiona are nevoie de obiecte de tip comand adecvate: proprietile InsertCommand, DeleteCommand a at i UpdateCommand trebuie s indice ctre comenzi valide. Returneaz s a a a de ecare dat numrul de a a nregistrri afectate. a

10.1.2

Proprieti at

1. DeleteCommand, InsertCommand, SelectCommand, UpdateCommand de tip Command, contin comenzile ce se execut pentru selectarea a sau modicarea datelor sursa de date. Mcar proprietatea Selectn a Command trebuie s indice ctre un obiect valid, pentru a se putea a a face popularea setului de date. 2. MissingSchemaAction de tip enumerare MissingSchemaAction, determin ce se face atunci cnd datele care sunt aduse nu se potrivesc a a peste schema tablei care sunt depuse. Poate avea urmtoarele valori: n a Add - implicit, DataAdapter adaug coloana la schema tablei a

AddWithKey - ca mai sus, dar adaug i informatii relativ la cine as este cheia primar a Ignore - se ignor lipsa coloanei respective, ceea ce duce la pierdere a de date pe DataSet Error - se genereaz o exceptie de tipul InvalidOperationExcepa tion.

10.2

Clasa DataSet

Clasa DataSet nu mai face parte din biblioteca unui furnizor de date ADO.NET, ind standard. Ea poate s contin reprezentri tabelare ale a a a datelor din baz precum i diferite restrictii i relatii existente. Marele ei a s s

216

CURS 10. ADO.NET (2)

avantaj este faptul c permite lucrul deconectat de la sursa de date, eliminnd a a felul acesta, necesitatea unei conexiuni permanente precum la DataReader. In un server de aplicatii sau un client oarecare poate apela la serverul de baze de date doar cnd preia datele sau cnd se dorete salvarea lor. Functioneaz a a s a strns legtur cu clasa DataAdapter care actioneaz ca o punte n a a a a a ntre un DataSet i sursa de date. Remarcabil este faptul c un DataSet poate face s a abstractie de sursa de date, procesarea datelor desfurnduse independent as a de ea. Figura 10.1 contine o vedere partial asupra clasei DataSet. a

Figura 10.1: Structura unui DataSet

10.2.1

Continut

Prezentm succint continutul unui DataSet: a 1. Colectia Tables contine 0 sau mai multe obiecte DataTable. Fiecare DataTable este compus dintr-o colectie de linii i coloane. a s 2. Colectia Relations contine 0 sau mai multe obiecte de tip DataRelation, folosite pentru marcarea legturilor printecopil. a a 3. Colectia ExtendedProperties contine proprieti denite de utilizator. at

10.2.2

Clasa DataTable

Datele sunt continute ntr-un DataSet sub forma unor tabele de tip DataTable. Aceste obiecte pot folosite att independent, ct i interiorul unui a a s n

10.2. CLASA DATASET

217

DataSet ca elemente ale colectiei Tables. Un DataTable contine o colectie Columns de coloane, Rows de linii i Constraints de constrngeri. s a DataColumn Un obiect DataColumn denete nu