Utilizarea obiectelor de conexiune ADO și a setului de înregistrări. Folosind biblioteca ADO (Microsoft ActiveX Data Object). Crearea unei baze de date MS Access

Capitolul din cartea lui Marco Cantu: Delphi 7. Pentru profesionisti
Autorii mulțumesc editurii PITER pentru materialele puse la dispoziție pentru publicare.

Rezumat al editorului

Mediul Delphi a fost și este în continuare cea mai bună combinație de programare orientată pe obiecte și programare vizuală, nu numai pentru Windows, dar acum și pentru Linux și în viitorul apropiat - pentru .NET. În această carte, autorul a încercat să elimine aproape complet materialul de referință, concentrându-se pe tehnologiile pentru utilizarea eficientă a Delphi. Cartea conține peste 300 de exemple. După cum a spus un abonat al grupului de știri, „cărțile lui Cantú sunt în esență filtrate Delphi., doar mai mari și mai bune.” Cartea este destinată programatorilor, dezvoltatorilor și oricărei persoane serios interesate de programare în mediul Delphi.

Tehnologia ADO (Capitolul 15)

De la mijlocul anilor 1980, programatorii RDBMS au încercat să găsească „cheia magică” a ușii care duce la țara independenței dintr-o anumită bază de date. Problema este că datele pot proveni dintr-o varietate de surse, fiecare având propriile sale specificități. Cu toate acestea, dezvoltarea aplicațiilor ar fi mult simplificată dacă ar fi posibil să se creeze un mecanism unificat pentru interacțiunea cu o mare varietate de surse de date. Acesta ar putea fi un software universal interfață API, care ar permite programatorilor să dezvolte aplicații care interacționează cu diferite surse de date în același mod. Astfel de aplicații ar putea fi utilizate pentru a interacționa cu diverse sisteme RDBMS în sine, precum și cu alte surse de date. De-a lungul timpului, diverse companii au propus multe soluții în acest domeniu. Cele mai semnificative sunt Microsoft ODBC (Open Database Connectivity) și Borland IDAPI (Integrated Database Application Programming Interface). Tehnologia Borland IDAPI este mai bine cunoscută ca BDE (Borland Database Engine).
La mijlocul anilor 1990, odată cu dezvoltarea și răspândirea COM (Component Model obiect), Microsoft a anunțat o tranziție treptată de la ODBC la utilizarea noii tehnologii OLE DB. Cu toate acestea, OLE DB, conform Microsoft însuși, este o interfață la nivel de sistem care ar trebui utilizată de programatorii de sistem. Tehnologia OLE DB este grea, complexă și foarte sensibilă la erori. Cere prea mult de la programator. Lucrul cu OLE DB este prea dificil. Pentru a face lucrul cu OLE DB mai ușoară, un suplimentar strat de aplicație, care se numește ADO (ActiveX Data Objects). Lucrul cu ADO este mult mai ușor decât lucrul cu OLE DB. Tehnologia ADO este destinată programatorilor de aplicații.
După cum sa discutat în capitolul 14, Borland a decis să înlocuiască BDE cu o nouă tehnologie numită dbExpress. Trebuie remarcat faptul că ADO amintește mai mult de BDE prin capacități și ideologie. Atât BDE, cât și ADO acceptă navigarea, manipularea setului de date, procesarea tranzacțiilor, actualizările în cache (în ADO acestea se numesc actualizări în lot). Cu alte cuvinte, conceptual și ideologic, ADO și BDE sunt tehnologii similare.

NOTĂ

Aș dori să-i mulțumesc lui Guy Smith Ferrier pentru că a scris acest capitol pentru cartea Mastering Delphi 6. Guy este programator, autor de cărți și articole și vorbește și la conferințe. Este autorul mai multor produse software comerciale și a numeroase sisteme interne atât pentru companiile mici cât și pentru cele mari. A scris numeroase articole pentru The Delphi Magazine, precum și pentru alte publicații. În plus, a vorbit la diferite conferințe din America de Nord și Europa. Tipul locuiește în Anglia cu soția, fiul și pisica lui.

În acest capitol ne vom uita la lucrul cu ADO. Ne vom uita, de asemenea, la dbGo, un set de componente Delphi care a fost inițial numit ADOExpress, dar a fost redenumit în Delphi 6, deoarece Microsoft se opune utilizării denumirii ADO în produsele terțe. În mediul Delphi, puteți lucra cu ADO fără ajutorul dbGo. Puteți importa biblioteca de tipuri ADO și puteți obține acces direct la interfețele ADO. Acesta este modul în care lucrați cu ADO în Delphi înainte de Delphi 5. Cu toate acestea, această abordare nu vă permite să profitați de infrastructura de baze de date încorporată a Delphi. Mai exact, nu veți putea folosi controale specifice datelor și nu veți avea acces la tehnologia DataSnap. Toate exemplele din acest capitol folosesc dbGo pentru a interacționa cu ADO. În primul rând, dbGo este inclus în pachetul standard Delphi, iar în al doilea rând, dbGo este o tehnologie foarte convenabilă. Indiferent dacă alegeți să utilizați sau nu dbGo, veți găsi util materialul din acest capitol.

NOTĂ

Pe lângă dbGo, puteți utiliza multe alte produse terțe pentru a interacționa cu ADO, cum ar fi Adonis, AdoSlutio, Diamond ADO și Kamiak.

Acest capitol acoperă următoarele subiecte:

    Microsoft Data Access Components (MDAC);

  • Fișiere de legătură de date;

    obținerea de informații despre schemă;

    folosind mecanismul Jet;

    procesarea tranzacției;

    seturi de înregistrări dezactivate și pe disc;

    model de portofoliu și configurarea MDAC.

MDAC (Componente de acces la date Microsoft)

ADO face parte de fapt dintr-o tehnologie mai mare numită Microsoft Data Access Components (MDAC). Termenul MDAC este o desemnare generală pentru toate tehnologiile legate de bazele de date dezvoltate de Microsoft. Acest set include ADO, OLE DB, ODBC și RDS (Remote Data Services). Auzi adesea că oamenii folosesc termenii MDAC și ADO în mod interschimbabil, dar acest lucru este incorect. De fapt, ADO este doar o parte a MDAC. Când vorbim despre versiunile ADO, ne referim la versiunile MDAC. Versiunile majore ale MDAC includ versiunile 1.5, 2.0, 2.1, 2.5 și 2.6. Microsoft distribuie MDAC ca produs separat. Acest produs poate fi descărcat gratuit de pe site-ul Microsoft. Nu numai atât, dar este de fapt gratuit să îl includeți în propriile produse (există anumite restricții, totuși, majoritatea dezvoltatorilor Delphi îndeplinesc toate aceste cerințe fără probleme). În plus, MDAC este inclus cu majoritatea produselor de baze de date Microsoft. Delphi 7 include MDAC 2.6.
Trebuie luate în considerare două circumstanțe importante. În primul rând, putem spune cu un grad ridicat de încredere că tehnologia MDAC este deja instalată pe computerele client ale utilizatorilor dumneavoastră. În al doilea rând, indiferent de versiunea de MDAC care a fost instalată pe computerele client ale utilizatorilor dvs., este sigur să spunem că această versiune va fi actualizată mai devreme sau mai târziu la cea mai recentă versiune (actuală) a MDAC. Actualizarea poate fi efectuată de dvs., de utilizatorii dvs. sau de unul dintre sistemele instalate aplicații Microsoft. O astfel de actualizare este practic imposibil de prevenit deoarece MDAC este instalat ca parte a unei aplicații utilizate pe scară largă, cum ar fi Internet Explorer. Trebuie adăugat că Microsoft acceptă doar cea mai recentă versiune de MDAC, precum și versiunea anterioară celei mai recente. Pe baza tuturor acestor lucruri, putem ajunge la o concluzie: aplicația dvs. trebuie să funcționeze cu cea mai recentă versiune a MDAC sau cu o versiune anterioară acesteia.
În calitate de dezvoltator ADO, ar trebui să revizuiți periodic paginile MDAC de pe site-ul Web Microsoft. Pentru a face acest lucru, vă rugăm să contactați www. microsoft.com/data. Aici puteți descărca cea mai recentă versiune de MDAC gratuit. De asemenea, este recomandat să descărcați MDAC SDK (13 MB) dacă nu aveți deja acest pachet. De fapt, SDK-ul MDAC este inclus în SDK-ul Platformă, așa că dacă aveți SDK-ul Platform, atunci aveți deja SDK-ul MDAC. Lăsați MDAC SDK să fie biblia dvs. Ar trebui să îl descărcați și să îl consultați în mod regulat pentru a obține informațiile de care aveți nevoie și pentru a răspunde la orice întrebări legate de ADO. Dacă aveți nevoie de informații legate de MDAC, primul loc pe care ar trebui să îl căutați este SDK-ul MDAC.

Furnizori OLE DB

Furnizorii OLE DB oferă acces la sursele de date. dbExpress folosește drivere în acest scop, în timp ce BDE utilizează legături SQL. În timpul procesului de instalare MDAC, furnizorii OLE DB enumerați în Tabelul 1 sunt instalați automat pe sistem. 15.1.

Tabelul 15.1. Furnizorii OLE DB incluși în MDAC

Conducător auto

Furnizor

Descriere

Drivere ODBC (implicit)

Microsoft.Jet.OLEDB.3.5

Numai bazele de date MS Access 97

Microsoft.Jet.OLEDB.4.0

Baze de date MS Access și alte baze de date

Baze de date MS SQL Server

Baze de date Oracle

Procesare analitică online

Exemplu de furnizor OLE DB pentru fișiere CSV

Pentru a vă crea proprii furnizori pentru date text simplu

Iată o listă cu acești furnizori.

    ODBC OLE DB este utilizat pentru compatibilitatea cu ODBC. Pe măsură ce aruncați o privire mai atentă asupra modului în care funcționează ADO, veți afla despre limitările inerente acestui furnizor.

    Jet OLE DB - suport pentru MS Access și alte baze de date locale. Vom reveni la revizuirea acestor furnizori mai jos.

    SQL Server oferă interoperabilitate cu SQL Server 7, SQL Server 2000 și Microsoft Database Engine (MSDE). MSDE este o versiune simplificată a SQL Server care elimină majoritatea instrumentelor și adaugă cod special care reduce în mod deliberat performanța dacă mai mult de cinci utilizatori se conectează la baza de date în același timp. Avantajele MSDE includ faptul că acest mecanism este distribuit gratuit și este pe deplin compatibil cu SQL Server.

    OLE DB pentru OLAP poate fi utilizat direct, dar este mai frecvent accesat prin ADO Multi-Dimentional (ADOMD). ADOMD este o tehnologie ADO suplimentară special concepută pentru procesarea analitică online (OLAP). Dacă ați lucrat anterior cu Delphi Decision Cube, Excel Pivot Tables sau Access Cross Tabs, atunci ați lucrat cu unul dintre formularele OLAP. Pe lângă furnizorii deja enumerați aici, Microsoft acceptă câțiva alți furnizori OLE DB care sunt incluși în alte produse sau ca parte a SDK-ului.

    Serviciile Active Directory OLE DB este inclusă în SDK-ul ADSI; AS/400 OLE DB și VSAM OLE DB sunt incluse cu SNA Server; Exchange OLE DB este inclus cu Microsoft Exchange 2000.

    Serviciul de indexare OLE DB face parte din Serviciul de indexare Microsoft - un mecanism intern Windows care accelerează căutarea informațiilor în fișiere prin construirea unui director cu informații despre fișiere. Serviciul de indexare este integrat în IIS și este adesea folosit pentru indexarea site-urilor Web.

    Internet Publishing OLE DB permite dezvoltatorilor să manipuleze directoare și fișiere folosind HTTP.

    Există și o categorie de furnizori OLE DB numită furnizori de servicii. După cum sugerează și numele, acești furnizori oferă servicii altor furnizori OLE DB și sunt adesea activați automat fără intervenția programatorului. De exemplu, Serviciul Cursor este activat dacă creați un cursor pe partea clientului, iar Furnizorul de set de înregistrări persistente este activat dacă intenționați să stocați date pe discul local.

În plus față de cei enumerați, există și un număr mare de alți furnizori OLE DB pentru MDAC. Furnizorii OLE DB sunt disponibili atât de la Microsoft, cât și de la furnizori terți. Lista furnizorilor OLE DB este foarte mare și se schimbă constant, așa că nu poate fi reprodusă în această carte. Pe lângă furnizorii independenți, mulți furnizori RDBMS furnizează și sprijină furnizorii OLE DB. De exemplu, Oracle își menține propriul furnizor OLE DB numit ORAOLEDB.

Probabil ați observat deja că furnizorul OLE DB pentru InterBase lipsește din listă. În primul rând, puteți utiliza driverul ODBC și, în al doilea rând, puteți utiliza furnizorul IBProvider dezvoltat de Dmitry Kovalenko (www.lipetsk.ru/prog/eng/index.html). În cele din urmă, puteți încerca să dezvoltați singur furnizorul. O modalitate convenabilă de a face acest lucru este să utilizați setul de instrumente de dezvoltare pentru furnizori OLE DB, dezvoltat de Binh Ly și disponibil la http://www.techvanguards.com/products/optk/install.htm.

Utilizarea componentelor dbGo

Programatorii deja familiarizați cu BDE, dbExpess sau IBExpress vor recunoaște cu ușurință componentele incluse în dbGo (Tabelul 15.2).

Tabelul 15.2. componentele dbGo

componenta dbGo

Descriere

Echivalent din kitul BDE

Conectarea la baza de date

Bază de date

Execută comanda SQL

Fără echivalent

Descendent multifuncțional al TDataSet

Fără echivalent

Încapsulează un tabel

Încapsulează SQL SELECT

Încapsulează o procedură stocată

Conectarea serviciilor de date la distanță

Fără echivalent

Cele patru componente ale setului de date (ADODataSet, ADOTable, ADOQuery și ADOStoredProc) sunt implementate în întregime de o clasă de bază comună, TCustomADODataSet. Această componentă este responsabilă pentru îndeplinirea majorității funcțiilor inerente setului de date. Componentele derivate sunt învelișuri subțiri care fac anumite capacități ale componentei de bază disponibile lumii exterioare. Astfel, componentele au multe caracteristici comune. Componentele ADOTable, ADOQuery și ADOStoredProc sunt concepute pentru a facilita adaptarea codului vizat de BDE. Cu toate acestea, trebuie reținut că aceste componente nu pot fi considerate echivalente complet identice cu componentele BDE similare. Cu siguranță, diferențele se vor manifesta atunci când se dezvoltă practic orice aplicație, cu posibila excepție a celor mai banale. Componenta ADODataSet ar trebui considerată componenta principală atunci când se dezvoltă noi programe, deoarece, în primul rând, această componentă este destul de convenabilă, iar în al doilea rând, interfața sa este similară cu interfața ADO Recordset. În acest capitol, voi demonstra utilizarea fiecăruia dintre componentele menționate.

Studiu de caz

Ajunge teorie, să trecem la treabă. Să plasăm componenta ADOTable pe formular. ADO folosește șiruri de conexiune pentru a indica la ce bază de date să se conecteze. Dacă știți ce faceți, puteți introduce manual șirul de conexiune. Cu toate acestea, în general, pentru a crea un șir de conexiune, se recomandă utilizarea unui editor special (editor de proprietăți ConnectionString), a cărui fereastră de lucru este prezentată în Fig. 15.1.

Faceți clic pe Build pentru a lansa editorul de șiruri de conexiune Microsoft. Fereastra sa de lucru este prezentată în Fig. 15.2. Să aruncăm o privire mai atentă la acest instrument, deoarece este un instrument important atunci când lucrați cu ADO. Prima filă arată furnizorii OLE DB și furnizorii de servicii instalați pe computerul dvs. Lista furnizorilor poate fi diferită pentru diferite versiuni de MDAC; în plus, furnizorii noi pot apărea în listă ca urmare a instalării de noi programe de aplicație pe computer. Să revenim la exemplul nostru. Selectați furnizorul Jet 4.0 OLE DB făcând dublu clic pe furnizorul Jet 4.0 OLE DB și fila Conexiune va apărea pe ecran. Aspectul acestei pagini poate varia de la diferiți furnizori. Pentru furnizorul Jet, editorul vă va solicita să introduceți numele bazei de date și informațiile de autentificare. Puteți selecta fișierul MDB al bazei de date Access care vine cu Delphi (de exemplu, C:\Program Files\Common Files\Borland Shared\Data\dbdemos.mdb). Click pe Butonul de testare Conexiune pentru a vă asigura că selecția dvs. este corectă.
În fila Avansat, puteți controla modul de acces la baza de date. Aici puteți configura accesul exclusiv sau numai pentru citire. Fila Toate listează toți parametrii șirului de conexiune. Această listă poate varia pentru diferiți furnizori OLE DB. Amintiți-vă bine această pagină, deoarece poate fi folosită pentru a rezolva multe probleme diferite. Închiderea Editorului Microsoft vă va duce înapoi la reductorul șirurilor de conexiune Borland. Fereastra de lucru a acestui editor va afișa șirul care va fi atribuit ConnectionString (aici l-am împărțit în mai multe rânduri pentru a fi mai ușor de citit):

Furnizor=Microsoft.Jet.OLEDB.4.0; Sursa datelor=C:\Program Files\Common Files\Borland Shared\Data\dbdemos.mdb; Persist Security Info=False


Un șir de conexiune este un șir simplu de caractere care listează parametrii și valorile acestora, separate prin punct și virgulă. Această linie poate fi editată manual. Parametrii și valorile acestora pot fi reconfigurați în timpul execuției programului; pentru a face acest lucru, trebuie să scrieți propriul set de rutine pentru a căuta un parametru în listă și pentru a face modificări la valoarea acestuia. Există, de asemenea, o modalitate mai ușoară: puteți copia șirul în lista de șiruri a lui Delphi și puteți utiliza mecanismul de perechi nume-valoare. Această tehnică va fi demonstrată în exemplul JetText, care va fi discutat mai târziu în secțiune „Accesarea fișierelor text prin Jet”.
După ce ați generat șirul de conexiune, puteți selecta tabelul. Extindeți lista de tabele folosind proprietatea TableName din fereastra Object Inspector. Selectați tabelul Client. Adăugați o componentă DataSource și un control DBGrid, apoi conectați-le împreună. Rezultatul este un program real, deși primitiv, care utilizează ADO (full sursă formatat ca exemplu FirstAdoExample). Pentru a vedea datele, setați proprietatea Active a setului de date la True sau deschideți setul de date în handlerul de evenimente FormCreate (așa cum se face în exemplu). A doua metodă evită problemele dacă baza de date nu este disponibilă în faza de proiectare.

Dacă intenționați să utilizați dbGo ca tehnologie principală de acces la baza de date, probabil că veți dori să mutați componenta DataSource în pagina ADO a Paletei de componente, astfel încât să nu trebuie să săriți constant de la o pagină la alta. Dacă utilizați ADO în combinație cu o altă tehnologie, puteți simula o configurare DataSource pe mai multe pagini. Pentru a face acest lucru, trebuie să creați un șablon de componente pentru componenta DataSource și să îl plasați pe pagina ADO.

Componenta ADOConnection

Când utilizați componenta ADOTable, aceasta își creează propria componentă de conexiune la baza de date în spatele dvs. Cu toate acestea, nu vi se cere să utilizați această conexiune specială. În general, ar trebui să vă creați propria conexiune folosind componenta ADOConnection, care este în esență echivalentul componentei dbExpress SQLConnection și al componentei BDE Database. Componenta ADOConnection vă permite să configurați corect procedura de autentificare, să controlați tranzacțiile, să executați direct comenzile adresate bazei de date și, de asemenea, vă permite să reduceți numărul de conexiuni care există în cadrul aplicației.
Utilizarea ADOConnection este destul de simplă. Plasați această componentă pe formular și setați-i proprietatea ConnectionString în același mod ca și pentru componenta ADOTable. Alternativ, puteți face dublu clic pe componenta ADOConnection (sau selectați Editor de componente din meniul contextual) pentru a accesa direct editorul șirurilor de conexiune. Dacă șirul de conexiune (ConnectionString) indică baza de date de care aveți nevoie, puteți dezactiva caseta de dialog pentru conexiunea la baza de date setând proprietatea LoginPrompt la False. Pentru a utiliza noua conexiune din exemplul anterior, setați valoarea ADOConnection1 la proprietatea Connection a componentei ADOTable1. Veți vedea că valoarea proprietății ConnectionString devine goală deoarece proprietățile Connection și ConnectionString se exclud reciproc. Avantajul utilizării ADOConnection este că șirul de conexiune este acum stocat într-un singur loc, în loc să fie stocat în mai multe componente diferite. Un alt avantaj mai important este că mai multe componente diferite pot folosi aceeași conexiune la serverul bazei de date. Dacă nu adăugați manual o componentă ADOConnection la programul dvs., fiecare componentă ADO va avea propria sa conexiune la server.

Fișiere de legătură de date

Deci, componenta ADOConnection vă permite să centralizați definiția șirului de conexiune într-un formular sau un modul de date. Cu toate acestea, această abordare are încă un dezavantaj major: dacă identificați o bază de date folosind un nume de fișier, calea către acea bază de date va fi codificată în interiorul aplicației executabile. Ca urmare, capacitățile aplicației vor fi semnificativ limitate. Pentru a rezolva această problemă, ADO utilizează ceea ce se numește Data Link Files. Un fișier de legătură de date este un șir de conexiune formatat ca fișier INI. De exemplu, Delphi instalează fișierul dbdems.udl, care conține următorul text:

Fișierul de legătură de date poate avea orice extensie, dar se recomandă utilizarea extensiei .UDL. Puteți crea un astfel de fișier folosind oricare editor de text. Alternativ, pentru a crea un astfel de fișier, puteți deschide o fereastră Windows Explorer, faceți clic dreapta într-unul dintre folderele de pe disc, selectați Nou > Document text, schimbați extensia fișierului în .UDL (presupun că pe sistemul dvs. Explorer afișează extensii de fișiere), apoi faceți dublu clic pe fișier - Acesta va lansa Microsoft Connection String Editor.
Dacă selectați Utilizați fișierul de legătură de date în editorul de proprietăți ConnectionString, proprietatea va avea automat șirul „NUME FIȘIER =" urmat de numele fișierului de legătură de date. Această tehnică este demonstrată în exemplul DataLinkFile. Fișierele de legătură de date pot fi plasate oriunde pe disc, dar ADO utilizează un director standard pentru a stoca aceste fișiere. Puteți afla numele acestui director folosind funcția DataLinkDir, care este definită în modulul ADODB. Dacă configurația este implicită în MDAC, atunci această funcție va returna următoarele:

C:\Program Files\Common Files\System\OLE DB\Data Links

Proprietăți dinamice

Imaginați-vă că dezvoltați un nivel mediu situat între clienți și mai multe baze de date. Pe de o parte, trebuie să creați o singură interfață software unificată pentru accesarea mai multor baze de date diferite, pe de altă parte, această interfață trebuie să ofere acces la capacitățile specifice fiecărei baze de date. Pentru a rezolva ambele probleme, puteți proiecta o interfață grea care este suma capabilităților tuturor bazelor de date cu care este proiectat să interacționeze. Fiecare clasă a unei astfel de interfețe trebuie să includă toate proprietățile și metodele posibile, dar numai un subset de proprietăți și metode ale clasei poate fi folosit pentru a lucra cu o anumită bază de date. Sper că nu este nevoie să vă dovedesc că această soluție nu este cea mai bună. Pentru a rezolva această problemă, ADO utilizează proprietăți dinamice. De fapt, toate interfețele ADO, precum și componentele lor corespunzătoare dbGo, au o proprietate numită Proprietăți. Această proprietate este o colecție de proprietăți specifice bazei de date curente. Aceste proprietăți pot fi accesate prin specificarea numărului lor de index, de exemplu:

ShowMessage(ADOTable1.Properties.Value);

Cu toate acestea, în majoritatea cazurilor este mai convenabil să folosiți numele: ShowMessage(ADOConnection1.Properties["DBMS Name"].Value); Setul de proprietăți dinamice este determinat de tipul obiectului și de furnizorul OLE DB. Pentru a vă face o idee despre importanța proprietăților dinamice, voi observa că componente precum ADOConnection sau Recordset acceptă aproximativ 100 de proprietăți dinamice. După cum veți vedea în acest capitol, proprietățile dinamice sunt utilizate pe scară largă în ADO pentru a rezolva o mare varietate de probleme.

Un eveniment important legat de utilizarea proprietăților dinamice este evenimentul OnRecordsetCreate. Acest eveniment a apărut pentru prima dată în Delphi 6. Evenimentul OnRecordsetCreate este declanșat imediat după crearea unui Recordset, dar înainte ca componenta să fie deschisă. Acest eveniment este util pentru setarea acelor proprietăți dinamice care pot fi setate numai atunci când Recordset-ul este într-o stare închisă.

Obținerea informațiilor despre schemă

ADO folosește metoda OpenSchema a componentei ADOConnection pentru a obține informații despre schemă. Această metodă ia patru parametri:

    Tipul de date care vor fi returnate de metoda OpenSchema. Această valoare este de tip TSchemaInfo: un set de 40 de valori, inclusiv liste de tabele, indici, coloane, vizualizări și proceduri stocate.

    Un filtru care trebuie aplicat datelor înainte ca acestea să fie returnate. Un exemplu al acestui parametru va fi demonstrat puțin mai târziu.

    GUID-ul pentru cererea specifică furnizorului. Acest parametru este utilizat numai dacă primul parametru este egal cu valoarea lui siProviderSpecific.

    Componenta ADODataSet în care vor fi returnate datele. Această opțiune ilustrează o temă comună în ADO: dacă o metodă returnează unele date, scrie acele date într-un Recordset sau, în terminologia Delphi, o componentă ADODataSet.

Pentru a utiliza metoda OpenSchema, trebuie să deschideți ADOConnection. Următorul cod, care face parte din exemplul OpenSchema, preia lista de chei primare pentru fiecare tabel și le populează în componenta ADODataSet:

ADOConnection1.OpenSchema(siPrimaryKeys, EmptyParam, EmptyParam, ADODataSet1);

Fiecare câmp din cheia primară corespunde unui rând din setul de date rezultat. Astfel, dacă un tabel are o cheie primară formată din două câmpuri, vor exista două rânduri corespunzătoare acestui tabel în setul de date rezultat. Valoarea EmptyParam indică faptul că parametrului i se atribuie o valoare goală, ceea ce înseamnă că parametrul este ignorat. Rezultatul codului este prezentat în Fig. 15.3.


Dacă treceți EmptyParam ca al doilea parametru, setul de date rezultat include toate informațiile de tipul specificat pentru întreaga bază de date. Foarte des, pentru comoditate, doriți să filtrați informațiile. Desigur, puteți aplica un filtru tradițional Delphi setului de date rezultat în acest scop (puteți folosi proprietățile Filter și Filtered sau evenimentul OnFilterRecord pentru aceasta). Cu toate acestea, în acest caz, filtrarea se va face pe partea clientului. Al doilea parametru vă permite să filtrați mai eficient pe partea sursă a informațiilor despre schemă. Un filtru este definit ca o matrice de valori. Fiecare element de matrice are o semnificație specială legată de tipul de date returnate. De exemplu, o matrice de filtru de cheie primară include trei elemente: director (adică baza de date), schemă și numele tabelului. Acest exemplu returnează o listă de chei primare în tabelul Client:

var Filtru: OLEVariant; ÎNCEPE Filtru:= VarArrayCreate(, varVariant); Filtru := "CLIENT"; ADOConnection1.OpenSchema(siPrimaryKeys, Filter, EmptyParam, ADODataSet1); Sfârşit;

NOTĂ

Aceleași informații pot fi obținute folosind ADOX. ADOX este o tehnologie ADO suplimentară care vă permite să preluați și să modificați informațiile despre schemă. În SQL, echivalentul ADOX este DDL (Data Definition Language), adică instrucțiunile CREATE, ALTER, DROP și DCL (Data Control Language), adică instrucțiunile GRANT, REVOKE. dbGo nu suportă direct tehnologia ADOX, dar puteți importa biblioteca de tip ADOX și o puteți utiliza în aplicațiile Delphi. Spre deosebire de metoda OpenSchema, implementarea Delphi a ADOX nu este universală, deci nu este întotdeauna convenabilă de utilizat. Dacă doriți doar să obțineți informații despre schemă, dar nu să le schimbați, de obicei este mai convenabil să utilizați metoda OpenSchema în acest scop.

Folosind mecanismul Jet

Acum că aveți o înțelegere de bază despre MDAC și ADO, putem trece la motorul Jet. Pentru unii, acest mecanism este de interes, pentru alții este complet inutil. Dacă lucrați cu Access, Paradox, dBase, Excel, Lotus 1-2-3, HTML sau date stocate în fișiere text, atunci materialul prezentat aici vă va fi util. Dacă nu sunteți interesat de formatele enumerate aici, puteți sări peste toată această secțiune.
De obicei, Jet este asociat cu bazele de date Microsoft Access. Într-adevăr, Access este sistemul principal cu care interacționează Jet. Cu toate acestea, pe lângă Access, Jet vă permite să lucrați cu multe alte surse de date locale. Mulți oameni nu sunt conștienți de acest lucru, dar acesta este unul dintre principalele avantaje ale Jet. Interacțiunea cu Access prin Jet este relativ simplă în modul său standard de operare, așa că nu vom acoperi acest mod de utilizare a Jet aici. În schimb, vom arunca o privire mai atentă asupra modului în care Jet interacționează cu alte formate.

NOTĂ

Motorul Jet este inclus în unele (dar nu în toate) versiunile MDAC. În special, lipsește din versiunea 2.6. La un moment dat, a existat o mulțime de controverse cu privire la dacă programatorii care foloseau instrumente de dezvoltare non-Microsoft ar putea include motorul Jet cu produsele lor software. Oficial se crede că acest lucru este posibil. Jet poate fi descărcat gratuit de pe site-ul Microsoft și este inclus cu multe produse Microsoft.

Există doi furnizori OLE DB pentru motorul Jet: Jet 3.51 OLE DB și Jet 4.0 OLE DB. Furnizorul OLE DB Jet 3.51 folosește Jet 3.51 și acceptă numai Access 97. Dacă veți folosi doar Access 97 și nu vă mutați la Access 2000, Jet 3.51 va oferi în general performanțe mai bune decât furnizorul OLE DB Jet 4.0.
Furnizorul OLE DB Jet 4.0 acceptă driverele Access 97, Access 2000 și IISAM (Installable Indexed Sequential Access Method). Driverele ISAM instalate sunt scrise special pentru motorul Jet și oferă acces la formate precum Paradox, dBase și fișiere text. Abilitatea de a utiliza aceste drivere face din Jet un instrument util și convenabil. Lista completă a driverelor ISAM instalate pe computer este determinată de setul de software instalat pe sistem. Această listă se află în registru la:

HKEY_LOCAL_MACHINE\Software\Microsoft\Jet\4.0\ISAM Formats

Jet este livrat cu drivere pentru Paradox, dBase, Excel, fișiere text și HTML.

Import si export

Motorul Jet este convenabil de utilizat pentru importarea și exportul de date. Procesul de export de date este același pentru fiecare format exportat și constă în executarea instrucțiunii SELECT în formatul specific. Să ne uităm la un exemplu de export de date dintr-o bază de date Access din exemplul DBDemos într-un tabel Paradox. Pentru a face acest lucru, adăugați o ADOConnection activă numită ADOConnection1 la programul JetImportExport. Această conexiune folosește motorul Jet pentru a deschide baza de date. Următorul cod exportă tabelul Client într-un fișier în format Paradox Customer.db:

SELECT * INTO Client IN „C:\tmp” „Paradox 7.x;” DE LA CLIENT

Să ne uităm la componentele acestei expresii SQL. Cuvântul cheie INTO specifică noul tabel care va fi creat ca rezultat al instrucțiunii SELECT. Înainte de a executa acest cod, un tabel cu acest nume nu trebuie să existe în baza de date. Cuvântul cheie IN specifică baza de date în care este adăugat noul tabel. În Paradox, acesta trebuie să fie un director care există deja pe disc. Imediat după numele bazei de date este numele driverului IISAM care va fi folosit pentru a exporta datele. Trebuie să adăugați un punct și virgulă (;) la sfârșitul numelui driverului. Cuvântul cheie FROM este o componentă standard a oricărei expresii SELECT. În exemplul luat în considerare, această operație este efectuată folosind componenta ADOConnection1; în loc de un nume de director fix, este folosit directorul programului curent:

Nou fisier Excel cu numele dbdemos.xls este creat în directorul programului curent. Acest document Excel adaugă un registru de lucru numit Client care conține toate datele din tabelul Client din baza de date Access numită dbdemo. mdb.
Iată o altă expresie care exportă aceleași date într-un fișier HTML:

ADOConnection1.Execute("SELECT * INTO IN "" + CurrentFolder + "" "HTML Export;" FROM CUSTOMER");

În acest caz, baza de date este un director (ca în Paradox). Numele tabelului include extensia .htm, astfel încât numele tabelului trebuie să fie cuprins între paranteze drepte. Vă rugăm să rețineți că driverul IISAM nu se numește doar HTML, ci HTML Export. După cum sugerează și numele, driverul vă permite doar să exportați date, dar nu vă permite să le importați.
În cele din urmă, să ne uităm la driverul de import HTML al Jet, care este o completare utilă pentru exportul HTML. Adăugați o componentă ADOTable în formular. Configurați ConnectionString pentru a utiliza furnizorul OLE DB Jet 4.0. Setați parametrul Extended Properties al șirului de conexiune la HTML Import. Pentru numele bazei de date, specificați numele fișierului HTML care a fost creat ca urmare a exportului (puțin mai devreme), mai precis, Customer.htm. Acum setați proprietatea TableName la Client. Deschideți foaia de calcul - tocmai ați importat date dintr-un fișier HTML. Vă rugăm să rețineți că, dacă încercați să actualizați datele, sistemul va afișa o eroare, deoarece driverul este doar de import. Dacă ați creat propriul fișier HTML care conține tabele și doriți să deschideți aceste tabele folosind acest driver, trebuie să vă amintiți că numele tabelului este valoarea etichetei de lege din secțiunea tabel HTML.

Lucrul cu cursoare

Fiecare dintre seturile de date ale ADO are două proprietăți care merg mână în mână și au un impact semnificativ asupra aplicației dumneavoastră. Acestea sunt proprietățile CursorLocation și CursorType. Dacă doriți să înțelegeți cum funcționează un set de date ADO, trebuie să învățați aceste două proprietăți.

Locația cursorului (proprietatea CursorLocation)

Proprietatea CursorLocation determină modul în care datele sunt preluate și modificate. Această proprietate poate fi setată la una dintre cele două valori: clUseClient (cursor pe partea clientului) sau clUseServer (cursor pe partea serverului). Alegerea valorii afectează foarte mult funcționalitatea, performanța și scalabilitatea bazei de date.
Cursorul client este servit de motorul de cursor ADO. Acest motor este un exemplu excelent de furnizor de servicii OLE DB: oferă servicii pentru alți furnizori OLDE DB. Motorul de cursor ADO gestionează procesarea datelor la nivelul clientului. Când deschideți un set de date, toate datele din setul de rezultate sunt descărcate de pe server pe computerul client. După aceasta, datele sunt stocate în memorie, actualizate și procesate folosind ADO Cursor Engine. Această abordare este similară cu utilizarea ClientDataSet în aplicațiile dbExpress. Avantajul este că, după transferul datelor către partea clientului, orice manipulări cu aceste date sunt efectuate mult mai rapid. În plus, deoarece manipulările sunt efectuate în memorie, ADO Cursor Engine este mai puternic decât orice cursor de pe server. În continuare, voi arunca o privire mai atentă la aceste beneficii, precum și la alte tehnologii bazate pe cursoare client (în special, seturi de înregistrări dezactivate și persistente). Cursorul din partea serverului este controlat de RDBMS însuși. Într-o arhitectură client-server bazată pe produse precum SQL Server, Oracle sau InterBase, aceasta înseamnă că cursorul este controlat pe un computer server la distanță. În cazul unei baze de date desktop, cum ar fi Access sau Paradox, cursorul serverului este controlat de produsul software care servește baza de date. Adică, în mod logic, cursorul se află pe „server”, dar fizic baza de date împreună cu cursorul se află pe computerul client. În general, cursorii de pe partea de server se încarcă mai repede decât cursorii de pe partea de client, deoarece atunci când deschideți un set de date cu un cursor de pe partea de server, nu este nevoie să mutați toate datele pe partea de client. Acest lucru face ca cursoarele de server să fie mai potrivite pentru difuzare seturi mari date, adică atunci când computerul client nu are memorie suficientă pentru a stoca întregul set de date. Pentru a înțelege capacitățile ambelor tipuri de cursoare, cel mai bine este să vă uitați la modul în care funcționează într-o anumită situație. De exemplu, puteți lua situația blocării înregistrărilor. Voi vorbi mai multe despre blocare puțin mai târziu. (Dacă doriți să blocați o înregistrare, veți avea nevoie de un cursor de server, deoarece RDBMS trebuie să știe că înregistrarea este blocată.)
O altă caracteristică de luat în considerare atunci când alegeți locația cursorului este scalabilitatea. Cursoarele serverului sunt situate pe partea serverului. Cu cât mai mulți utilizatori se conectează la baza de date, cu atât mai multe cursoare este creat pe server. Cu fiecare cursor nou, sarcina pe server crește. Astfel, pe măsură ce numărul de utilizatori crește, performanța generală a sistemului poate scădea semnificativ. Folosind cursoare de pe partea clientului, puteți crește semnificativ scalabilitatea aplicației dvs. Deschiderea unui cursor client vă va costa mai mult, deoarece în timpul procesului de deschidere toate datele sunt transferate către client, dar menținerea unui cursor client este mai puțin împovărătoare pentru server, deoarece sarcina principală asociată cu aceasta este plasată pe computerul client.

Tip cursor (proprietatea CursorType)

Tipul de cursor este determinat în mare măsură de locația cursorului. Există cinci tipuri de cursoare, dintre care unul nu este utilizat. Un tip neutilizat se numește nespecificat. Există multe valori în ADO care corespund unei valori nespecificate. În Delphi, aceste valori nu sunt niciodată utilizate efectiv. Aceste valori sunt prezente în Delphi doar pentru că sunt prezente în ADO. Faptul este că tehnologia ADO a fost dezvoltată inițial pentru limbaje precum Visual Basic și C. În aceste limbi, lucrați direct cu obiecte, fără suportul unor mecanisme auxiliare precum dbGo. Ca rezultat, puteți crea un set de înregistrări deschis (în terminologia ADO, un set de înregistrări) fără a specifica o valoare pentru fiecare dintre proprietăți. Astfel, valorile unor proprietăți vor fi nedefinite. În acest caz, proprietatea este setată la nespecificat. Cu toate acestea, în dbGo aveți de-a face cu componente. Componentele au constructori. Un constructor este o funcție care obligatoriu inițializează fiecare dintre proprietățile componentei. Când creați o componentă dbGo, fiecare dintre proprietățile sale are o anumită valoare. Ca rezultat, nu este nevoie să utilizați valoarea nespecificată.
Tipul de cursor afectează modul în care datele sunt citite și actualizate. Puteți utiliza unul dintre cele patru tipuri de cursor: Numai înainte, Static, Set de taste și Dinamic. Înainte de a discuta diferitele combinații de tipuri și locații de cursor, este un lucru important de reținut: pentru cursoarele de pe partea clientului, puteți utiliza un singur tip: un cursor static. Toate celelalte tipuri de cursoare pot fi utilizate numai pe partea serverului. Să aruncăm o privire mai atentă asupra tipurilor de cursoare în ordinea creșterii costurilor asociate cu întreținerea lor.

    Numai înainte (doar înainte). Acest tip de cursor este cel mai puțin costisitor din punct de vedere al costului. Cu alte cuvinte, astfel de cursoare oferă cea mai mare performanță. După cum sugerează și numele, cursorul numai înainte vă permite să vă deplasați printr-un set de date într-o direcție de la început la sfârșit. Cursorul citește de pe server numărul de înregistrări specificat în proprietatea CacheSize (implicit 1), de fiecare dată când lasă ultima înregistrare în memoria cache locală, citește următorul lot de înregistrări de pe server. Orice încercare de deplasare către începutul setului de înregistrări în afara memoriei cache-ului local are ca rezultat o eroare. Acest comportament este similar cu comportamentul unui set de date din biblioteca dbExpress. Cursorul Forwardonly nu este potrivit pentru a crea o interfață cu utilizatorul în care utilizatorul are control asupra direcției de mișcare. Cu toate acestea, un astfel de cursor este destul de potrivit pentru efectuarea de operațiuni batch, generarea de rapoarte, atunci când construiți aplicații web fără stat - în oricare dintre aceste situații începeți de la începutul setului de date și vă deplasați spre sfârșitul setului de date. Când se ajunge la final, setul de date este închis.

    Static (static). Când utilizați un cursor static, setul de date este mutat complet în partea clientului și accesat folosind o fereastră de dimensiune CacheSize. Ca rezultat, utilizatorul poate naviga prin setul de date în ambele direcții. Dezavantajul este că datele sunt statice - actualizările, completările și ștergerile înregistrărilor efectuate de alți utilizatori nu sunt vizibile pentru un cursor static deoarece datele cursorului au fost deja citite.

    Set de chei (set de chei). Pentru a înțelege cum funcționează acest cursor, împărțiți cuvântul Keyset în două părți: key și set. Cheia este o cheie, adică, în acest context, un identificator de înregistrare. Adesea, aceasta se referă la cheia primară. Setul este un set sau o colecție. Se dovedește a fi un „set de chei”. Când deschideți un set de date de pe server, este citită o listă completă a tuturor cheilor. De exemplu, dacă un set de date este generat folosind expresia SELECT * FROM CUSTOMER, atunci lista de chei poate fi generată folosind expresia SELECT CUSTID FROM CUSTOMER. Setul de chei este stocat pe partea clientului până când cursorul este închis. Când o aplicație are nevoie de date, furnizorul OLE DB citește rândurile tabelului folosind setul de chei existent în acest scop. Ca urmare, clientul se ocupă întotdeauna cu date actualizate. Cu toate acestea, un set de chei este static, în sensul că odată ce cursorul este deschis, chei noi nu pot fi adăugate la set și nici chei nu pot fi îndepărtate din set. Cu alte cuvinte, dacă un alt utilizator adaugă noi înregistrări la tabel, acele modificări nu vor fi vizibile pentru client. Înregistrările șterse devin inaccesibile și orice modificare a cheilor primare (în general, utilizatorilor le este interzis să schimbe cheile primare) devin, de asemenea, inaccesibile.

    Dinamic. Acesta este cel mai scump cursor. Un cursor dinamic funcționează în același mod ca un cursor de taste. Diferența este că setul de chei este recitit de pe server de fiecare dată când aplicația are nevoie de date care nu se află în cache. Deoarece valoarea implicită a proprietății ADODataSet.CacheSize este 1, solicitările de citire a datelor apar destul de des. Vă puteți imagina încărcarea suplimentară pe care acest cursor o plasează pe serverul DBMS și pe rețea. Cu toate acestea, atunci când folosește acest cursor, clientul este conștient nu numai de modificările datelor, ci și de adăugările și ștergerile efectuate de alți clienți.

Nu întotdeauna primești ceea ce ceri

Acum că știți despre tipurile și locațiile de cursor, ar trebui să vă avertizez că nu sunt permise toate combinațiile de tipuri și locații de cursor. De obicei, această limitare este legată de tipul RDBMS și/sau furnizorul OLE DB. De exemplu, dacă cursorul este situat pe partea clientului, tipul de cursor poate fi doar static. Puteți observa singur acest comportament. Adăugați componenta ADODataSet în formular, configurați proprietatea ConnectionString pentru a se conecta la orice bază de date, apoi setați proprietatea ClientLocation la clUseCursor și proprietatea CursorType la ctDynamic. Acum modificați valoarea proprietății Active la True și observați proprietatea CursorType. Valoarea acestei proprietăți se va schimba imediat în ctStatic. Ar trebui sa faci concluzie importantă: Nu întotdeauna primești exact ceea ce ceri. Când deschideți un set de date, verificați întotdeauna valorile proprietăților - unele dintre ele își pot schimba spontan valorile. Diferiți furnizori OLE DB au modificări diferite ale proprietăților. Permiteți-mi să dau doar câteva exemple:

    Furnizorul OLE DB Jet 4.0 schimbă majoritatea tipurilor de cursor în Keyset;

    Furnizorul SQL Server OLE DB schimbă adesea Keyset și Static în Dynamic;

    Furnizorul Oracle OLE DB modifică toate tipurile de cursor la Forward-only;

    Furnizorul ODBC OLE DB poate efectua o mare varietate de modificări ale tipului de cursor, în funcție de driverul ODBC utilizat.

Lipsa contorului

Când încercați să citiți proprietatea RecordCount a unui set de date ADO, uneori descoperiți că proprietatea este egală cu -1. Un cursor Forwardonly nu știe câte înregistrări sunt în setul de date până când ajunge la sfârșitul setului. Din acest motiv, proprietatea RecordCount este egală cu valoarea - 1. Un cursor static știe întotdeauna câte înregistrări sunt în setul de date, deoarece un cursor static citește toate datele din set în momentul în care este deschis. Un cursor Keyset știe, de asemenea, numărul de înregistrări din set, deoarece preia un set fix de valori cheie din baza de date atunci când setul de date este deschis. Deci, pentru cursoarele Static și Keyset, puteți accesa proprietatea RecordCount și puteți obține numărul exact de înregistrări din set. Un cursor dinamic nu poate cunoaște în mod fiabil numărul de înregistrări, deoarece de fiecare dată când citește date, citește din nou setul de chei, astfel încât proprietatea RecordCount pentru acest cursor este întotdeauna egală cu -1. Puteți evita cu totul utilizarea proprietății RecordCount și, în schimb, puteți utiliza instrucțiunea SELECT COUNT(*) FROM table_name. Cu toate acestea, ca rezultat, veți obține o valoare inexactă pentru numărul de înregistrări din tabelul bazei de date - această valoare nu coincide întotdeauna cu numărul de înregistrări din setul de date.

Indicii de clienți

Unul dintre avantajele cursoarelor la nivelul clientului este capacitatea de a crea indecși locali sau pe partea clientului. Imaginați-vă că aveți un set de date ADO cu un cursor client și că acest set este alăturat tabelului Client din exemplul DBDemos. Imaginați-vă că un DBGrid este conectat la acest set. Setați proprietatea IndexFieldNames la CompanyName. Grila va afișa imediat înregistrările, ordonându-le în funcție de valoarea câmpului CompanyName. Este important de reținut că ADO nu recitește datele din sursă pentru a construi indexul. Indexul este format pe baza datelor stocate în memorie. Datorită acestui fapt, în primul rând, indexul se formează destul de repede și, în al doilea rând, nu se creează încărcare suplimentară în rețea și DBMS. În caz contrar, aceleași date ar trebui transmise prin rețea din nou și din nou într-o ordine de sortare diferită.
Proprietatea IndexFieldNames are alte caracteristici interesante. De exemplu, setați această proprietate la Country;CompanyName - veți vedea că înregistrările sunt sortate mai întâi în funcție de numele țării și apoi în funcție de numele companiei. Acum setați proprietatea IndexField-Names la CompanyName DESC (cuvântul cheie DESC trebuie să fie cu majuscule, nu desc sau Desc). Ca urmare, înregistrările vor fi sortate în ordinea descrescătoare a valorilor.
Această caracteristică simplă, dar puternică, vă permite să rezolvați una dintre cele mai presante probleme asociate cu programarea bazelor de date. Utilizatorilor le place să pună întrebarea inevitabila și frustrantă, dar complet justificabilă pentru programatori: „Pot să dau clic pe antetul coloanei grilei pentru a-mi sorta datele?” Există mai multe modalități de a rezolva această problemă. De exemplu, puteți utiliza un control standard (necunoaștere a datelor), cum ar fi ListView, care acceptă un mecanism de sortare încorporat. În plus, puteți gestiona evenimentul OnTitleClick al componentei DBGrid și, în cadrul handlerului, puteți reexecuta instrucțiunea SQL SELECT, adăugând la aceasta echipa potrivita COMANDA PENTRU. Cu toate acestea, oricare dintre aceste soluții nu poate fi numită complet satisfăcătoare. Dacă datele sunt stocate în cache pe partea client (am discutat deja despre această abordare când am vorbit despre componenta ClientDataSet), puteți utiliza un index generat în memoria computerului client. Adăugați următorul handler de evenimente OnTitleClick pentru grilă (codul sursă complet este inclus cu exemplul ClientIndexes):

procedură Tfrom1.DBGrid1TitleClick(Coloană: Tcolumn); ÎNCEPE dacă ADODataSet1.IndexFieldNames = Column.Field.FieldName apoi ADODataSet1.IndexFieldNames:= Column.Field.FieldName + „DESC” altfel ADODataSet1.IndexFieldNames:= Column.Field.FieldName Sfârşit;

Acest cod simplu verifică dacă indexul curent se bazează pe câmpul care corespunde coloanei grilei pe al cărei antet a fost făcut clic. Dacă da, atunci se construiește un nou index pe baza aceluiași câmp, dar în ordine descrescătoare. Dacă nu, atunci se formează un nou index pe baza coloanei. Când utilizatorul face clic pe antetul unei coloane pentru prima dată, intrările sunt sortate în ordine crescătoare a valorilor. Când utilizatorul face clic pe aceeași coloană a doua oară, intrările sunt sortate în ordine descrescătoare. Puteți îmbunătăți acest handler pentru a permite utilizatorului să facă clic pe mai multe titluri în timp ce țineți apăsată tasta Ctrl. În acest caz, se pot forma indici mai complexi.

NOTĂ

Același lucru se poate face folosind componenta ClientDataSet, dar această componentă nu acceptă cuvântul cheie DESC, așa că va trebui să scrieți cod suplimentar pentru a sorta în ordine descrescătoare. Mai mult, dacă ordinea de sortare este schimbată, componenta ClientDataSet va reconstrui indexul - aceasta este o operație inutilă și posibil lentă.

Clonarea

Tehnologia ADO acceptă multe caracteristici interesante. Vă puteți plânge că abundența de caracteristici are ca rezultat o creștere a dimensiunii codului executabil care trebuie instalat pe computerul client. Cu toate acestea, datorită multitudinii de capabilități ale ADO, puteți construi aplicații puternice și de încredere. Una dintre caracteristicile convenabile ale ADO este capacitatea de a clona. Un set de înregistrări clonat este set nouînregistrări, care are exact același set de proprietăți ca și cel original. În primul rând, voi explica cum are loc clonarea, apoi voi vorbi despre motivul pentru care este necesară.

NOTĂ

Componenta ClientDataSet acceptă și clonarea, dar nu am menționat această caracteristică în Capitolul 13.

Pentru a clona un set de date (în ADO, un set de înregistrări), utilizați metoda Clone. Puteți clona orice set de date ADO, dar în acest exemplu vom folosi componenta ADOTable. Programul DataClone (Fig. 15.6) conține două componente ADOTable - una dintre ele este conectată la date, iar a doua este goală. Ambele seturi de date sunt conectate la o sursă de date și la o rețea. Când utilizatorul face clic pe butonul Clonează setul de date, este executată o singură linie de cod care clonează setul de date:

ADOTable2.Clone(ADOTable1);



Această linie clonează setul de date ADOTable1 și plasează clona rezultată în setul de date ADOTable2. Acest lucru vă oferă două vizualizări ale acelorași date. Fiecare set are propriul său indicator către înregistrarea curentă și propria copie a informațiilor de stare, astfel încât clona nu afectează în niciun fel copia originală a datelor. Acest comportament face clonele un instrument excelent pentru lucrul cu un set de date fără a afecta datele originale. O altă caracteristică interesantă: puteți crea mai multe intrări active diferite - clone diferite intrările active pot varia. Acest tip de funcționalitate nu poate fi implementat în Delphi folosind un singur set de date.

Un set de date poate fi clonat numai dacă acceptă marcaje. Din acest motiv, cursoarele numai înainte și dinamice nu pot fi clonate. Pentru a determina dacă un set de înregistrări acceptă marcaje, puteți utiliza metoda Supports (de exemplu, ADOTable1.Supports()). Un efect secundar al clonării este că marcajele create de una dintre clone pot fi folosite de toate celelalte clone.

Procesarea tranzacției

În secțiunea „Utilizarea tranzacțiilor” din Capitolul 14, am discutat că mecanismul tranzacției permite dezvoltatorilor să grupeze operațiunile individuale ale bazei de date într-o singură procedură, consecventă din punct de vedere logic.
Procesarea tranzacțiilor în ADO se realizează folosind componenta ADOConnection; pentru aceasta sunt utilizate metodele BeginTrans, CommitTrans și RollbackTrans. Aceste metode funcționează similar cu cele ale dbExpress și BDE. Pentru a studia mecanismul tranzacției încorporat în ADO, vom folosi programul TransProcessing. Programul include o componentă ADOConnection, al cărui șir de conexiune (proprietatea ConnectionString) este configurat să utilizeze furnizorul OLE DB Jet 4.0 și să acceseze fișierul dbdemos.mdb. Programul conține o componentă ADOTable conectată la tabelul Client și asociată cu componentele DataSource și DBGrid pentru a afișa date. În cele din urmă, programul conține trei butoane concepute pentru a efectua următoarele comenzi:

ADOConnection1.BeginTrans; ADOConnection1.CommitTrans; ADOConnection1.RollbackTrans;


Folosind acest program, puteți face modificări în baza de date și apoi puteți anula tranzacția, ceea ce înseamnă anularea acelor modificări. Aceasta va restabili baza de date la starea în care se afla înainte de începerea tranzacției. Trebuie remarcat faptul că procesarea tranzacțiilor se realizează diferit în funcție de baza de date și de furnizorul OLE DB. De exemplu, dacă vă conectați la Paradox folosind un furnizor ODBC OLE DB, veți primi un mesaj de eroare care indică faptul că baza de date sau furnizorul OLE DB nu poate începe o tranzacție. Pentru a determina nivelul de suport pentru tranzacții, puteți utiliza proprietatea dinamică Transaction DDL a unei conexiuni:

dacă ADOConnection1.Properties["Transaction DDL"].Value > DBPROPVAL_TC_NONE atunci ADOConnection1.BeginTrans;


Dacă încercați să accesați aceeași bază de date Paradox folosind furnizorul Jet 4.0 OLE DB, nu va apărea nicio eroare, dar din cauza limitărilor furnizorului, nu veți putea anula tranzacția.
O altă diferență ciudată apare atunci când lucrați cu Access: dacă utilizați furnizorul ODBC OLE DB, veți putea folosi tranzacții, dar nu veți putea folosi tranzacții imbricate. Încercarea de a deschide o nouă tranzacție în paralel cu o tranzacție activă existentă va avea ca rezultat o eroare. Cu toate acestea, dacă utilizați motorul Jet, veți putea folosi tranzacții imbricate fără probleme.

Tranzacții imbricate

Folosind TransProcessing, încercați următorul test.

    Activați tranzacția.

    Schimbați câmpul ContactName al intrării Around The Horn din Thomas Hardy în Dick Solomon.

    Activați o altă tranzacție imbricată.

    Schimbați câmpul ContactName din înregistrarea piețelor cu dolari de jos din Elizabeth Lincoln în Sally Solomon.

    Derulați înapoi tranzacția internă.

    Confirmați tranzacția externă.

Ca urmare, modificările ar trebui făcute numai la intrarea Around The Horn. Dacă tranzacția internă este efectuată și derulați înapoi tranzacția externă, rezultatul va fi că nu vor fi făcute modificări în baza de date (chiar și modificările făcute ca parte a tranzacției interne). Acesta este modul în care funcționează tranzacțiile imbricate. Există o limitare: Accesul acceptă doar cinci niveluri de imbricare a tranzacțiilor.
ODBC nu acceptă tranzacții imbricate, iar furnizorul Jet OLE DB acceptă până la cinci niveluri de imbricare. Furnizorul SQL Server OLE DB nu acceptă deloc imbricarea tranzacțională. Trebuie să știți că imbricarea tranzacțiilor poate fi gestionată diferit în funcție de versiunea serverului SQL sau a driverului. Informațiile necesare pot fi obținute din documentare și prin experimente. Se pare că, în majoritatea cazurilor, tranzacția exterioară determină dacă modificările făcute în tranzacția internă vor fi aplicate bazei de date.

Atributele componentei ADOConnection

Dacă intenționați să utilizați tranzacții imbricate, mai trebuie să luați în considerare un lucru. Componenta ADOConnection are o proprietate Atribute care determină modul în care se comportă conexiunea atunci când o tranzacție este confirmată sau anulată. Proprietatea Attributes stochează un set de valori TXActAttributes, care este inițial gol. Enumerarea TXActAttributes include doar două valori: xaCommitRetaining și xaAbortRetaining (această valoare este uneori scrisă incorect ca xaRollbackRetaining, deoarece acesta este, în mod logic, un nume mai corect). Dacă atributul xaCommitRetaining este prezent în proprietatea Attributes, o nouă tranzacție este deschisă automat când tranzacția este comisă. Dacă atributul xaAbortRetaining este prezent în proprietatea Atribute, o nouă tranzacție este deschisă automat când tranzacția este anulată. Astfel, dacă adăugați ambele aceste atribute la proprietatea Atribute, orice acțiune va fi efectuată în cadrul unei tranzacții: când următoarea tranzacție este finalizată, următoarea va fi activată automat.
În cele mai multe cazuri, programatorii preferă să nu lucreze în acest mod și să controleze în mod independent deschiderea tranzacțiilor, astfel încât aceste atribute sunt utilizate rar. Ar trebui luată în considerare utilizarea acestor atribute împreună cu tranzacțiile imbricate. Dacă creați o tranzacție imbricată și setați proprietatea Atribute la , tranzacția exterioară nu se va finaliza niciodată. Să luăm în considerare această succesiune de evenimente.

    Începe tranzacția externă.

    Tranzacția internă începe.

    O tranzacție internă este în curs de comitere sau anulată.

Pe baza setării proprietății Atribute, se începe automat o nouă tranzacție internă.
Astfel, tranzacția externă nu se poate finaliza niciodată, deoarece tranzacțiile interne se succed în mod indisolubil. Putem concluziona că proprietatea Atribute și utilizarea tranzacțiilor imbricate se exclud reciproc.

Tipuri de blocare

ADO acceptă patru abordări diferite pentru blocarea datelor de actualizare: ltReadOnly, ltPesimistic, ltOptimistic și ltBatchOptimistic (există și un tip ltUnspecified, dar din motivele menționate mai devreme acest tip nu este utilizat în Delphi). Pentru a configura modul de blocare, utilizați proprietatea LockType. În această secțiune, voi vorbi pe scurt despre toate cele patru metode de blocare. Fiecare dintre aceste metode va fi discutată mai detaliat în secțiunile următoare.
Valoarea ltReadOnly indică faptul că datele sunt doar în citire - actualizarea nu este posibilă. Deoarece clientul nu poate modifica datele, nu este necesară blocarea.
Valorile ltPesimist și ltOptimist oferă blocare pesimistă și, respectiv, optimistă. Aceste moduri sunt echivalente cu modurile BDE corespunzătoare. Cu toate acestea, în comparație cu BDE, tehnologia ADO oferă o mai mare flexibilitate: alegerea modului de blocare vă aparține. Dacă utilizați un BDE, decizia de a utiliza blocarea pesimistă sau optimistă este luată de driverul BDE. Dacă utilizați o bază de date desktop, cum ar fi Paradox sau dBase, atunci driverul BDE utilizează blocarea pesimistă. Dacă utilizați o bază de date client-server, cum ar fi InterBase, SQLServer sau Oracle, driverul BDE utilizează blocarea optimistă.

Blocare pesimistă

În acest context, termenii „optimist” și „pesimist” caracterizează așteptarea programatorului cu privire la posibilitatea unor conflicte la actualizarea simultană a datelor conținute în baza de date de către mai mulți utilizatori. Blocarea pesimistă sugerează că probabilitatea apariției unui conflict este mare. Cu alte cuvinte, utilizatorii modifică datele conținute în baza de date în același timp și există o probabilitate mare ca doi utilizatori să încerce să modifice aceeași înregistrare a bazei de date în același timp. Pentru a preveni un astfel de conflict, înregistrarea este blocată în momentul în care începe editarea. Intrarea rămâne blocată până când editarea este finalizată sau anulată. Dacă orice alt utilizator încearcă să editeze aceeași intrare (blocata), nu va putea face acest lucru: va fi lansată o excepție „Actualizarea nu poate fi făcută, intrarea este blocată”.
Această abordare va fi familiară programatorilor care au lucrat anterior cu baze de date desktop, cum ar fi dBase și Paradox. Avantajul este că utilizatorul știe că odată ce începe editarea unei înregistrări, poate finaliza cu succes editarea și poate face modificări în baza de date. Dezavantajul este că utilizatorul are control complet asupra blocării înregistrării. Dacă utilizatorul este bine versat în aplicație, editarea unei singure intrări poate dura doar câteva secunde, dar într-un mediu client-server cu mulți utilizatori, chiar și câteva secunde pot părea o eternitate. Pe de altă parte, un utilizator care nu bănuiește ar putea începe să editeze o postare și să plece la prânz. În acest caz, intrarea va rămâne blocată până când acesta se întoarce la locul de muncă. Dacă nu luați măsuri speciale, în acest timp nimeni nu va putea edita intrarea blocată. Pentru a evita acest lucru, folosesc adesea un cronometru: dacă tastatura și mouse-ul rămân inactive pentru o perioadă lungă de timp, programul deblochează automat înregistrarea.
O altă problemă cu blocarea pesimistă este că blocarea pesimistă necesită un cursor pe partea serverului. Am discutat mai devreme că locația cursorului afectează tipurile de cursoare disponibile. Acum vedem că locația cursorului afectează și metodele de blocare. Vom discuta mai detaliat despre beneficiile utilizării cursoarelor de pe partea clientului mai târziu în acest capitol. Dacă decideți să profitați de aceste beneficii, atunci nu veți putea profita de blocarea pesimistă.

Actualizare de date

Suportul pentru îmbinări actualizabile este unul dintre principalele motive pentru care programatorii folosesc componenta ClientDataSet (sau actualizările stocate în cache în BDE). O interogare care implică unirea a două tabele returnează utilizatorului un singur tabel, iar utilizatorul dorește să poată modifica înregistrările din acel tabel. Luați în considerare următoarea instrucțiune SQL:

SELECT * FROM Products, Suppliers WHERE Suppliers.SupNo=Products.SupNo

Această interogare returnează o listă de produse împreună cu furnizorii care furnizează acele produse. Motorul BDE tratează orice conexiune SQL ca un tabel numai pentru citire. Ideea este că adăugarea, actualizarea și ștergerea înregistrărilor dintr-un tabel alăturat este ambiguă. De exemplu, dacă un utilizator adaugă o înregistrare nouă la un tabel îmbinat, ar trebui adăugat un nou furnizor și un nou produs în tabel sau ar trebui să se limiteze doar la adăugarea unui produs? Arhitectura ClientDataSet/Provider vă permite să specificați tabelul principal de actualizat (această carte nu acoperă asta) și să configurați în continuare actualizările SQL. Acest lucru este parțial acoperit în Capitolul 14 și îl voi acoperi și în Capitolul 16. ADO acceptă un mecanism de actualizare în cache numit actualizări batch, care funcționează în același mod ca și BDE. În secțiunea următoare, voi arunca o privire mai atentă asupra mecanismului de actualizare în lot al ADO. Cu toate acestea, pentru a rezolva problema actualizării conexiunilor SQL, puteți face fără ajutorul acestui mecanism. Faptul este că ADO acceptă actualizarea conexiunilor SQL. Componenta ADODataset a fost adăugată la programul JoinData, pe baza expresiei SQL dată mai devreme. Dacă rulați programul, puteți edita unul dintre câmpuri și puteți salva modificările în baza de date (pentru a face acest lucru, trebuie doar să treceți la o altă înregistrare). Nu vor apărea erori, deoarece ADO va actualiza cu succes baza de date. Cert este că, spre deosebire de BDE, ADO adoptă o abordare mai practică. În ADO, atunci când vă alăturați mai multor tabele, fiecare câmp știe cărui tabel îi aparține. Dacă actualizați un câmp din tabelul Produse și publicați modificările în baza de date, actualizarea generează o instrucțiune SQL UPDATE care actualizează valoarea câmpului din tabelul Produse din baza de date. Dacă, pe lângă câmpul tabel Produse, modificați și câmpul tabel Furnizori, atunci sunt generate două instrucțiuni SQL UPDATE - câte una pentru fiecare tabel.
Când adăugați linie nouăÎntr-o conexiune SQL, mecanismul ADO se comportă într-un mod similar. Dacă inserați un rând și adăugați valori numai pentru câmpurile din tabelul Produse, atunci este generată o singură instrucțiune SQL INSERT care adaugă o înregistrare nouă în tabelul Produse. Dacă introduceți valori pentru câmpurile din ambele tabele, sunt generate două instrucțiuni SQL INSERT, câte una pentru fiecare tabel. Ordinea în care sunt executate aceste expresii este importantă deoarece un produs nou poate face referire la un furnizor nou, astfel încât informațiile despre furnizor trebuie adăugate mai întâi la tabelul Furnizori. O problemă serioasă apare atunci când ștergeți un rând dintr-un tabel alăturat. Când încercați să ștergeți un rând dintr-un tabel alăturat, veți vedea un mesaj de eroare. Textul exact al mesajului depinde de versiunea ADO, precum și de baza de date utilizată. Acest mesaj poate fi confuz, deoarece cel mai probabil nu va avea nimic de-a face cu cauza reală a problemei. Problema este că nu puteți șterge o înregistrare la care se referă alte înregistrări. În exemplul nostru, probabil că veți vedea un mesaj care spune că înregistrarea produsului nu poate fi ștearsă, deoarece există alte înregistrări care fac referire la acea înregistrare. Cu toate acestea, dacă faceți câteva experimente, veți descoperi că eroarea apare indiferent dacă există alte înregistrări în baza de date care fac referire la produsul care este șters sau dacă nu există astfel de înregistrări. Pentru a înțelege cauza problemei, trebuie să utilizați aceeași abordare ca atunci când adăugați înregistrări noi la un tabel alăturat. Când un rând dintr-un tabel alăturat este șters, ADO generează două instrucțiuni SQL DELETE: una pentru tabelul Furnizori și una pentru tabelul Produse. Declarația DELETE pentru tabelul Produse reușește, dar instrucțiunea DELETE pentru tabelul Furnizori eșuează - un furnizor de produse nu poate fi șters din tabel, deoarece are de obicei mai multe înregistrări de produse care fac referire la el.

Dacă doriți să vedeți exact ce instrucțiuni SQL sunt generate ca urmare a rulării unei anumite comenzi ADO, rețineți că, dacă utilizați SQL Server, puteți vizualiza aceste expresii folosind instrumentul SQL Server Profiler.

Chiar dacă înțelegeți exact cum funcționează procesul, este util să priviți problema prin ochii utilizatorului. Aș paria că atunci când un utilizator șterge o înregistrare dintr-un tabel alăturat, 99 la sută din timp intenționează să ștergă doar înregistrarea produsului, lăsând înregistrarea furnizorului neschimbată. Din fericire, puteți obține acest rezultat dacă utilizați o proprietate dinamică specială a Unique Table. Cu acesta, puteți specifica că ștergerea unui rând afectează numai tabelul Produse și nu tabelul Furnizori. Pentru aceasta este folosit următorul cod:

ADOQuery1.Properties[„Unique Table”].Value:= „Produse”;

Nu puteți atribui o valoare acestei proprietăți în momentul proiectării, așa că această expresie trebuie plasată în handlerul de evenimente OnCreate.

Actualizări în lot

Când se utilizează mecanismul de actualizare în lot, orice modificări făcute de utilizator sunt acumulate în memoria locală. Mai tarziu pachet complet aceste modificări pot fi făcute bazei de date într-o singură operațiune. Evident, această abordare oferă beneficii de performanță, dar există și alte avantaje care o fac convenabilă. În special, atunci când folosește mecanismul de actualizare în lot, utilizatorul poate face modificări chiar și atunci când este deconectat de la baza de date. Această caracteristică poate fi folosită pentru a oferi o experiență utilizator în modul offline, folosind tehnologii precum Briefcase, precum și în aplicații web bazate pe un alt mecanism ADO numit RDS (Remote Data Services). Puteți activa actualizările în lot pentru orice set de date ADO. Pentru a face acest lucru, trebuie să setați proprietatea LockType la ltBatchOptimistic înainte ca setul de date să fie deschis. În plus, trebuie să setați proprietatea CursorLocation la clUseClient deoarece actualizările batch sunt gestionate de ADO Cursor Engine. Ca urmare, orice modificări pe care utilizatorul le face setului de date vor fi stocate în zona delta (această zonă stochează lista modificărilor). Setul de date va apărea ca și cum datele ar fi fost modificate, dar de fapt informațiile despre modificări sunt stocate în memorie - aceste modificări nu sunt făcute în baza de date. Pentru a publica modificările în baza de date (le transferați din memorie în baza de date), trebuie să apelați metoda ApplyBatch (această metodă este echivalentă cu metoda ApplyUpdates a mecanismului BDE):

ADODataSet1.UpdateBatch;

Dacă doriți să anulați tot ce s-a acumulat în memorie, utilizați metoda CancelBatch - aceasta este un analog al metodei CancelUpdates. Există multe alte metode și proprietăți cu nume similare utilizate în cadrul ADO Batch Update, al BDE Cache Update și al mecanismelor de stocare în cache Client-DataSet. De exemplu, ca și în BDE, proprietatea UpdateStatus a unui set de date ADO poate fi utilizată pentru a afla starea unei anumite înregistrări: dacă înregistrarea a fost adăugată, modificată, ștearsă sau nu a suferit nicio modificare. Această proprietate este foarte utilă dacă doriți să evidențiați intrările modificate în culoare sau să afișați starea acestora în bara de stare. Există unele diferențe de sintaxă, de exemplu, în loc de a apela RevertRecord în ADO, se folosește apelarea CancelBatch(arCurrent); O caracteristică foarte utilă a mecanismului de actualizare în cache al BDE lipsește din ADO: un mecanism pentru urmărirea dacă actualizările există nepublicate în baza de date. BDE utilizează proprietatea UpdatesPending în acest scop. Această proprietate conține valoarea True dacă s-au făcut modificări la setul de date care nu au fost încă publicate în baza de date. Această proprietate este convenabilă de utilizat în handlerul de evenimente OnCloseQuery:

Cu toate acestea, având cunoștințe necesareși creativitate, vă puteți scrie propria funcție ADOUpdatesPending. Pentru a scrie o astfel de funcție, trebuie să știți că seturile de date ADO acceptă o proprietate FilterGroup, care funcționează la fel ca un filtru. Spre deosebire de proprietatea Filter a unui set de date standard, care filtrează datele în funcție de anumite condiții, proprietatea FilterGroup poate filtra în funcție de starea înregistrării. Există mai multe stări de filtrare, iar una dintre ele corespunde valorii fgPendingRecords. Această stare corespunde înregistrărilor care au fost modificate, dar informațiile de modificare nu au fost încă publicate în baza de date. Deci, pentru a arunca o privire asupra tuturor modificărilor care au fost făcute, dar nu au fost publicate, trebuie doar să rulați două linii de cod:

ADODataSet1.FilterGroup:= fgPendingRecords; ADODataSet1.Filtered:= Adevărat;

Desigur, după executarea acestor comenzi, setul de date va conține înregistrări care au fost șterse, iar câmpurile acestor înregistrări vor fi goale - acest lucru nu este foarte convenabil, deoarece nu veți putea înțelege ce înregistrare a fost ștearsă. (Prima versiune de ADOExpress a funcționat diferit: toate valorile câmpurilor au fost afișate pentru înregistrările șterse.)
Pentru a rezolva problema UpdatesPending, va trebui să utilizați clonarea setului de date (această caracteristică a fost discutată mai devreme). Funcția ADOUpdatesPending setează proprietatea FilterGroup astfel încât setul de date să conțină numai informații despre modificările efectuate, dar nepublicate. Acum trebuie să verificăm dacă există cel puțin o înregistrare în setul de date. Dacă cel puțin o intrare este prezentă, înseamnă că unele modificări nu au fost încă publicate în baza de date. Dacă după filtrare setul de date este gol, înseamnă că toate modificările efectuate anterior au fost deja publicate în baza de date. Cu toate acestea, dacă încercați să verificați numărul de înregistrări dintr-un set de date real, resetarea proprietății FilterGroup va compensa indicatorul către înregistrarea curentă - UI va răspunde imediat la aceasta. Pentru a evita acest lucru, utilizați o clonă de set de date:

funcţie ADOUpdatePending(ADODataSet: TCustomADODataSet): boolean; var Clona: ​​TADODataSet; ÎNCEPE Clone:= TADODataSet.Create(nil); încerca Clone.Clone(ADODataSet); Clone.FilterGroup:= fgPendingRecords; Clone.Filtered:= Adevărat; Rezultat:= nu (Clone.BOF și Clone.EOF); Clona.Închide; in cele din urma Clonare.Free; Sfârşit; Sfârşit;

În această funcție, clonați setul de date original, setați proprietatea FilterGroup și apoi verificați dacă indicatorul se află atât la începutul, cât și la sfârșitul setului de date. Dacă da, atunci setul de date este gol.

Blocare optimistă

Anterior, ne-am uitat la utilizarea proprietății LockType și am discutat cum funcționează blocarea pesimistă. În această secțiune ne vom uita la blocarea optimistă. Blocarea optimistă nu este preferată doar pentru sistemele de înaltă performanță, ci este și tipul de blocare utilizat atunci când se efectuează actualizări în serie.
Blocarea optimistă presupune că este puțin probabil să apară un conflict între doi utilizatori care încearcă să editeze aceeași intrare în același timp. Rezultă că orice utilizator are voie să editeze oricare dintre intrări în orice moment. Consecințele conflictelor sunt procesate atunci când modificările sunt salvate în baza de date. Astfel, conflictele sunt văzute ca excepții de la regulă. Dacă doi utilizatori încearcă să salveze modificări în aceeași înregistrare, numai primul utilizator va putea face acest lucru; al doilea utilizator va fi refuzat. Acest comportament apare în aplicațiile care rulează sub modelul Briefcase, precum și în aplicațiile web care nu au o conexiune persistentă la baza de date și, prin urmare, nu pot implementa blocarea pesimistă. Spre deosebire de blocarea pesimistă, blocarea optimistă nu necesită blocarea pe termen lung a resurselor: înregistrarea este blocată doar în momentul actualizării. Astfel, în medie, consumul de resurse este mai mic, iar baza de date este mai scalabilă.
Să ne uităm la un exemplu. Imaginați-vă că aveți o componentă ADODataSet conectată la tabelul Client din exemplul dbdemos.mdb; proprietatea LockType este setată la ltBatchOptimistic și conținutul setului de date este afișat în DBGrid. Să presupunem, de asemenea, că aveți un buton care, atunci când faceți clic, apelează metoda UpdateBatch. Rulați două copii ale acestui program (acesta este programul BatchUpdates). Începeți editarea intrării din prima copie a programului. Din motive de simplitate, folosesc un computer în această demonstrație, dar același lucru se va întâmpla dacă editarea aceleiași înregistrări se face pe două computere.

    Selectați Piețele cu dolari de jos din Canada și schimbați-i numele în Piețe cu franci de jos.

    Salvați modificările în baza de date; pentru a face acest lucru, pur și simplu mergeți la o altă înregistrare și faceți clic pe butonul de actualizare în lot.

    În a doua copie a programului, găsiți aceeași intrare și schimbați numele companiei în Bottom-Pound Markets.

    Navigați la o altă intrare și faceți clic pe butonul de actualizare în lot. Actualizarea nu va funcționa.

Ca și în cazul altor mesaje de eroare ADO, textul mesajului va depinde nu numai de versiunea ADO, ci și de cât de atent ați urmărit secvența de acțiuni descrisă. În ADO 2.6, veți vedea următorul mesaj de eroare pe ecran: Rândul nu poate fi localizat pentru actualizare. Este posibil ca unele valori să fi fost modificate de la ultima citire. Rândul de actualizat nu poate fi găsit. Este posibil ca unele valori ale rândului să se fi modificat de la ultima citire.
Acesta este scopul blocării optimiste. Pentru a actualiza o înregistrare, se execută următoarea instrucțiune SQL:

UPDATE CUSTOMER SET CompanyName="Bottom-Pound Markets" WHERE CustomerID="BOTTM" AND CompanyName="Bottom-Pound Markets"

Expresia identifică o înregistrare folosind cheia primară și valoarea câmpului CompanyName așa cum erau atunci când înregistrarea a fost citită din baza de date în memorie. Este de așteptat ca o înregistrare de tabel să fie modificată ca rezultat al executării acestei expresii. Cu toate acestea, în exemplul pe care l-am analizat, niciuna dintre înregistrări nu este modificată ca urmare a executării expresiei. Acest rezultat este posibil numai dacă înregistrarea a fost ștearsă, cheia principală a fost schimbată sau câmpul care este modificat a fost modificat de cineva înaintea dvs. În oricare dintre aceste cazuri, actualizarea va eșua.
Dacă un al doilea utilizator ar încerca să modifice valoarea câmpului ContactName (dar nu CompanyName), atunci expresia de actualizare ar arăta astfel:

ACTUALIZAȚI SETUL CLIENT ContactName="Liz Lincoln" WHERE CustomerID="BOTTM" ȘI ContactName="Elizabeth Lincoln"

În cazul nostru, actualizarea ar avea succes deoarece celălalt utilizator nu ar schimba nici cheia primară, nici numele contactului. Acest comportament este similar cu modul Update Where Changed al mecanismului BDE. În loc de proprietatea UpdateMode utilizată în BDE, ADO utilizează proprietatea dinamică Dataset Update Criteria. Următoarea listă conține valori valide pentru această proprietate dinamică.

Nu presupuneți că unul dintre aceste moduri va fi de preferat pentru întreaga dvs. aplicație. În practică, alegerea modului este determinată de tipul de informații conținute în tabel. Să presupunem că tabelul Client are doar trei câmpuri: ID client, Nume și Oraș. Modificarea oricăruia dintre aceste câmpuri nu afectează în niciun fel valorile altor câmpuri din tabel, așa că într-o astfel de situație este foarte posibil să se folosească modul adCriteriaUpdCols (acest mod este folosit în mod implicit). Cu toate acestea, dacă pe lângă câmpurile enumerate, tabelul include și câmpul CodPoștal ( cod poștal), atunci actualizarea acestui câmp trebuie să fie coordonată cu actualizarea câmpului Oraș. Cu alte cuvinte, nu puteți permite unui utilizator să modifice câmpul Cod Postal și, în același timp, altui utilizator să modifice câmpul Oraș fără niciun acord cu primul utilizator. În acest caz, modul de actualizare adCriteriaAllCols va fi mai sigur. De asemenea, ar trebui să vorbiți despre modul în care ADO gestionează erorile atunci când actualizați mai multe înregistrări. În BDE și ClientDataSet, puteți utiliza evenimentul OnUpdateError în acest scop, care vă va permite să răspundeți la o eroare legată de actualizarea unei înregistrări și să rezolvați problema înainte de a trece la următoarea înregistrare. Nu există o astfel de opțiune în ADO. Puteți monitoriza progresul, succesul sau eșecul unei actualizări în lot folosind evenimentele OnWillChangeRecord și OnRecordChangeComplete, dar nu puteți modifica conținutul înregistrării care se actualizează și nu puteți încerca să o reintroduceți în baza de date, așa cum este posibil în BDE și ClientDataSet . O altă problemă este că, dacă apare o eroare în timpul unei actualizări în lot, procedura de actualizare nu se oprește, ci continuă să ruleze. Actualizarea lotului se efectuează până la sfârșit, adică până când toate modificările au fost făcute în baza de date (în acest caz pot apărea și alte erori). Ca urmare, este posibil să primiți un mesaj de eroare confuz sau incorect. Dacă au apărut mai multe erori în timpul unei actualizări în lot (înregistrările multiple nu au putut fi actualizate), ADO 2.6 va afișa următorul mesaj pe ecran: Operațiunea OLE DB în mai multe pași a generat erori. Verificați fiecare valoare de stare OLE DB, dacă este disponibilă. Nu s-a lucrat. Au apărut erori în timpul unei operații OLE DB în mai mulți pași. Dacă este posibil, verificați fiecare stare OLE DB. Nu a fost efectuată nicio lucrare. Problema este în ultima propoziție: nu s-a făcut nicio lucrare. ADO ne spune că nu s-a făcut nimic, dar nu este cazul. Înregistrarea care a cauzat eroarea nu a fost într-adevăr actualizată, dar toate celelalte înregistrări au fost publicate cu succes în baza de date.

Rezolvarea conflictelor de actualizare a datelor

În timpul procesului de actualizare, următoarea abordare ar fi rezonabilă: utilizatorul face modificările necesare la setul de date, apoi se efectuează o actualizare în lot, apar erori la actualizarea unor înregistrări, când procesul de actualizare este complet finalizat, utilizatorului i se oferă un lista de înregistrări problematice și având posibilitatea de a rezolva fiecare dintre conflicte. Pentru a obține o listă a tuturor înregistrărilor problematice, puteți utiliza valoarea fgConflictingRecords a proprietății FilterGroup:

ADODataSet1.FilterGroup:= fgConflictingRecords; ADODataSet1.Filtered:= Adevărat;

Pentru fiecare câmp al fiecărei înregistrări problematice, puteți spune utilizatorului trei valori cheie: valoarea câmpului care a fost conținut în înregistrare la momentul când această înregistrare a fost citită pentru prima dată din baza de date; valoarea câmpului care a fost atribuită câmpului de către acest utilizator; valoarea care este conținută în prezent în baza de date (adică în timpul încercării de actualizare). Următoarele proprietăți Tfield sunt utilizate pentru aceasta.

Cei care lucrează cu componenta ClienDataSet știu despre existența unei casete de dialog ReconcileErrorForm convenabile. Această casetă de dialog este generată automat, arată utilizatorului valorile câmpurilor vechi, noi și actuale ale înregistrării problematice și permite utilizatorului să selecteze o metodă pentru a rezolva conflictul. Din păcate, nu există un analog al acestei casete de dialog în ADO. Clasa TReconcileErrorForm a fost concepută special pentru componenta ClientDataSet, deci este foarte dificil de adaptat pentru utilizarea cu seturile de date ADO. De asemenea, trebuie spus și despre ordinea de funcționare a proprietăților menționate ale clasei TField. Aceste proprietăți se bazează pe obiectele ADO Fields la care se referă. Aceasta înseamnă că modul în care funcționează aceste proprietăți este determinat în întregime de furnizorul OLE DB pe care îl utilizați. Puteți doar să sperați că furnizorul pe care îl utilizați acceptă corect funcțiile de care aveți nevoie. Majoritatea furnizorilor fac o treabă bună în acest sens, dar furnizorul Jet OLE DB returnează aceeași valoare pentru proprietățile CurValue și OldValue. Mai exact, valoarea curentă a câmpului returnează valoarea care a fost conținută în câmp atunci când înregistrarea a fost citită pentru prima dată din baza de date. Cu alte cuvinte, Jet nu vă permite să determinați valoarea atribuită unui câmp de către un alt utilizator (cu excepția cazului în care luați niște pași suplimentari pentru a face acest lucru singur). Dacă utilizați furnizorul SQL Server OLEDB, puteți accesa proprietatea CurValue numai după ce metoda Resync a setului de date a fost executată, iar parametrul AffectRecords trebuie să fie egal cu valoarea adAffectGroup, iar parametrul ResyncValues ​​trebuie să conțină valoarea adResyncUnderlyingValues . Iată codul relevant:

adoCustomers.FilterGroup:= fgConflictingRecords; adoCustomers.Filtered:= adevărat; adoCustomers.Recordset.Resync(adAffectGroup, adResyncUnderlyingValues);

Seturi de înregistrări dezactivate

Acum că știți despre actualizările lot, putem începe să explorăm o altă caracteristică ADO: seturi de înregistrări dezactivate. Un set de înregistrări deconectat este un set de înregistrări care este deconectat de la conexiunea la baza de date. Utilizatorul poate lucra cu un astfel de set de înregistrări exact în același mod în care lucrează cu un set de înregistrări obișnuit, conectat. Aceasta este o caracteristică foarte impresionantă: practic nu există nicio diferență între seturile de înregistrări conectate și deconectate. Proprietățile și capacitățile sunt practic identice. Pentru a deconecta un set de înregistrări de la o conexiune, trebuie să setați proprietatea CursorLocation la clUseClient și proprietatea LockType la ltBatchOptimistic. Apoi setați proprietatea Connection la zero, ceea ce face ca setul de înregistrări să fie dezactivat:

Această caracteristică este acceptată și în BDE și alte tehnologii de date, dar pentru a face acest lucru trebuie să treceți la utilizarea unui Client-DataSet. Frumusețea ADO este că încă de la început îți poți proiecta aplicația ca și cum habar nu ai avea că un set de înregistrări ar putea fi deconectat de la baza de date. Utilizați componente normale dbGo în cel mai normal mod. După aceasta, puteți adăuga cu ușurință posibilitatea de a vă deconecta de la baza de date la programul dvs. ca și cum tocmai ați fi aflat despre existența acestei abilități. În acest caz, nu trebuie să schimbați codul principal al aplicației dvs.
Dezactivarea unui set de înregistrări poate fi necesară pentru:

    minimizați numărul total de conexiuni paralele la baza de date;

    asigurați-vă că aplicația funcționează offline (în conformitate cu modelul Briefcase).

Vom vorbi despre aplicațiile care funcționează în cadrul modelului Briefcase într-una din secțiunile următoare.
Majoritatea aplicațiilor de afaceri care operează sub conceptul client-server deschid tabele de baze de date și mențin o conexiune persistentă la baza de date atâta timp cât tabelul este deschis.
Cu toate acestea, în realitate, conexiunea este necesară doar în timpul a două operațiuni: preluarea datelor din baza de date și actualizarea datelor din baza de date. Imaginați-vă dacă ați modificat programul pentru a vă deconecta de la baza de date imediat după deschiderea unui tabel și preluarea datelor. Odată ce datele necesare sunt transferate pe computerul client, conexiunea este întreruptă. Iată codul relevant:

Dacă utilizați o abordare similară în aplicația dvs., numărul mediu de conexiuni la baze de date deschise în același timp va fi minim - conexiunile vor fi deschise doar pentru o perioadă scurtă de timp atunci când sunt cu adevărat necesare. Evident, o astfel de structură client-server este mult mai ușor de scalat. Serverul va putea deservi un număr semnificativ mai mare de clienți. Există și un dezavantaj: formarea unei conexiuni la unele (dar nu la toate) baze de date necesită timp semnificativ, într-o astfel de situație actualizarea lotului va fi mai lentă.

Pooling de conexiuni

Vorbind despre ruperea și redeschiderea conexiunilor ne face să ne întrebăm dacă conexiunile pot fi refolosite? Acest mecanism se numește Pooling de conexiuni. Când îl utilizați, când aplicația termină de funcționare cu o conexiune, conexiunea nu este distrusă, ci este pusă într-o zonă de depozitare (piscină) și poate fi apoi reutilizată. Acest proces este automat, desigur, cu condiția ca furnizorul OLE DB pe care îl utilizați să îl accepte și ca mecanismul să fie activat. În acest caz, nu trebuie luate măsuri suplimentare.
Performanța este principalul motiv pentru utilizarea unui astfel de mecanism. Adesea este nevoie de timp pentru a stabili o conexiune la o bază de date. Dacă aveți de-a face cu o bază de date desktop precum Access, conexiunea se stabilește practic instantaneu. Cu toate acestea, într-un mediu client/server, cum ar fi un server Oracle care este accesat printr-o rețea, poate dura câteva secunde pentru ca conexiunea să fie stabilită. Deci are sens să ne gândim reutilizare o resursă atât de valoroasă ca o conexiune la baza de date.
Când utilizați mecanismul de acumulare al ADO, de fiecare dată când o aplicație „distruge” un obiect ADOConnection, acel obiect este adăugat la un pool special (o locație de stocare temporară). Dacă devine necesar să se creeze o nouă conexiune în viitor, sistemul caută automat o conexiune adecvată în piscină. Dacă se găsește o conexiune existentă care are un șir de conexiune care se potrivește cu cel de care are nevoie utilizatorul, acea conexiune este reutilizată. Dacă nu se găsește o conexiune adecvată, se creează una. Conexiunile rămân în grup până când fie sunt revendicate, fie aplicația se închide sau expiră un timeout. Durata implicită de expirare este de 60 de secunde, dar începând cu MDAC 2.5 această valoare poate fi modificată. Pentru a face acest lucru, trebuie să specificați durata de expirare în cheia de registry HKEY_CLASSES_ROOT\ CLSID\ \SPTimeout. Procesul de acumulare și reutilizare a conexiunilor se realizează în mod transparent, fără acțiuni suplimentare din partea dezvoltatorului. Un mecanism similar de acumulare de conexiuni funcționează în BDE atunci când se utilizează MTS (Microsoft Transaction Server) și COM+, totuși, spre deosebire de BDE, mecanismul ADO acumulează conexiuni independent, fără Ajutor MTS sau COM+.
În mod implicit, mecanismul de acumulare a conexiunilor este activat pentru toți furnizorii MDAC OLE DB baze de date relaționale date (inclusiv SQL Server și Oracle). O excepție importantă este furnizorul Jet OLE DB. Dacă utilizați ODBC, puteți alege între acumularea de conexiuni ODBC și acumularea de conexiuni ADO, cu toate acestea, nu este recomandat să utilizați ambele mecanisme în același timp. Începând cu MDAC 2.1, în mod implicit, agregarea conexiunilor ADO este activată și agregarea conexiunilor ODBC este dezactivată.

NOTĂ

Indiferent de furnizorul OLE DB, acumularea de conexiuni nu are loc în mediul Windows 95.

Din păcate, ADO nu include instrumente care vă permit să monitorizați conținutul pool-ului de conexiuni. Cu toate acestea, puteți utiliza instrumentul SQL Server în acest scop Monitor de performanță, care vă va oferi informații despre conexiunile la o bază de date SQL Server.
Puteți activa sau dezactiva acumularea de conexiuni fie folosind registry, fie folosind șirul de conexiune. Registrul utilizează în acest scop parametrul OLEDB_SERVICES, care se află în secțiunea HKEY_CLASSES_ROOT\ CLSID\ . Această setare stochează o mască de biți care vă permite să dezactivați unele servicii OLE DB, inclusiv acumularea conexiunilor, înregistrarea tranzacțiilor și altele. Pentru a dezactiva acumularea de conexiuni folosind un șir de conexiune, adăugați secvența de caractere; OLE DB Services=-2 la sfârșitul șirului de conexiune. Pentru a activa agregarea conexiunilor pentru furnizorul Jet OLE DB, adăugați secvența;OLE DB Services=-1 la sfârșitul șirului de conexiune. Acest lucru va activa toate serviciile OLE DB.

Salvarea unui set de înregistrări în memoria permanentă (Set de înregistrări persistente)

Capacitatea de a stoca un set de înregistrări pe hard disk este o parte importantă a aplicațiilor Briefcase. Folosind această caracteristică, puteți salva conținutul unui set de înregistrări într-un fișier de pe hard disk-ul local. Puteți încărca ulterior datele din acest fișier într-un set de înregistrări. Printre alte beneficii, această caracteristică permite dezvoltatorilor să creeze adevărate aplicații cu un singur nivel - puteți instala o aplicație de bază de date fără a instala baza de date în sine. Datorită acestui fapt, instalarea programului necesită foarte puțin spațiu pe hard disk-ul clientului. Pentru a salva un set de date pe hard disk, utilizați metoda SaveToFile:

Trebuie reținut că (spre deosebire de ClientDataSet) ADO nu conține suport nativ pentru formatul XML - motorul MSXML este folosit pentru a genera cod XML. Prin urmare, utilizatorul aplicației dumneavoastră va trebui să instaleze Internet Explorer 5.0 sau să descarce MSXML de pe site-ul Microsoft.
Dacă intenționați să stocați datele local în format XML, fiți conștienți de unele dezavantaje ale acestei abordări:

    Fișierele XML (create de motorul ADO, totuși, ca orice alte fișiere XML) au dimensiuni semnificative, dimensiunea lor depășește semnificativ dimensiunea unui fișier ADTG care conține aceleași date (de obicei dimensiunea unui fișier XML este de două ori mai mare decât dimensiunea unui fișier XML). ADTG -file similar);

    XML-ul generat de ADO este un format specific Microsoft (este cazul multor alte companii care își mențin propria generație XML), ceea ce înseamnă că XML-ul generat de ADO nu poate fi citit de ClientDataSet și invers (din fericire, această problemă poate fi rezolvată prin utilizarea componentei XML Transform a Delphi, care vă permite să transformați între diferite structuri XML).

Dacă intenționați să utilizați mecanismul de persistență al setului de înregistrări doar într-o aplicație cu un singur nivel și nu intenționați să utilizați modelul Briefcase, atunci puteți utiliza componenta ADODataSet și puteți seta proprietatea CommandType la cmdFile și proprietatea CommandText la numele fișierului. Acest lucru elimină nevoia de a apela manual metoda LoadFromFile. Cu toate acestea, va trebui să apelați în continuare metoda SaveToFile. Într-o aplicație Briefcase, această abordare ar fi prea restrictivă, deoarece în astfel de aplicații setul de date este utilizat în două moduri.

Model servieta

Acum că sunteți familiarizat cu actualizările loturilor, seturile de înregistrări dezactivate și stocarea seturilor de înregistrări în fișiere locale, puteți începe să explorați modelul Servietă. Ideea principală este să oferi utilizatorului posibilitatea de a lucra cu aplicația ta chiar și atunci când nu se poate conecta la baza de date, adică atunci când utilizatorul călătorește sau se află în biroul unei companii client. Problema este că în biroul clientului, utilizatorul nu se poate conecta la rețeaua corporativă a companiei dumneavoastră, ceea ce înseamnă că nu se poate conecta la serverul bazei de date. Aceasta înseamnă că datele nu pot ajunge la laptopul utilizatorului și nu pot fi actualizate.
Pentru a oferi o experiență de utilizator offline, veți avea nevoie de tehnologii precum seturi de date dezactivate și stocarea seturi de date pe disc local. Imaginați-vă că ați dezvoltat o aplicație client-server care oferă acces la un server de baze de date și satisface pe deplin nevoile utilizatorului. Acum, utilizatorul cere să vă asigurați că această aplicație funcționează în modul offline, adică chiar și atunci când nu există nicio modalitate de a vă conecta la serverul bazei de date. Pentru a face acest lucru, trebuie să adăugați aplicației posibilitatea de a salva date pe hard disk-ul local al utilizatorului. Cu alte cuvinte, înainte de a porni într-o călătorie, utilizatorul trebuie să dea comanda pentru a pregăti aplicația pentru funcționarea offline. Această comandă salvează fiecare tabel într-un fișier local folosind metoda SaveToFile. Rezultatul este o colecție de fișiere ATDG sau XML de pe hard diskul utilizatorului care reprezintă conținutul bazei de date. După aceasta, utilizatorul își poate deconecta laptopul de la rețea și poate continua să lucreze cu aplicația sa obișnuită în modul offline.
Aplicația ar trebui să detecteze automat dacă este offline sau online. Pentru a determina acest lucru, puteți încerca să vă conectați la baza de date și să verificați dacă conexiunea este deschisă. De asemenea, puteți verifica prezența unui fișier de portofoliu local sau puteți utiliza propriul steag special. Dacă aplicația rulează offline, în loc să se conecteze la baza de date, trebuie să preia date dintr-un fișier local folosind metoda LoadFromFile. Când doriți să publicați date în baza de date, în loc să utilizați metoda UpdateBatches, aplicația dvs. ar trebui să apeleze metoda SaveToFile pentru fiecare tabel. Dacă puteți comunica cu baza de date prin rețea, trebuie să setați proprietatea Connected a componentei ADOConnection la True, precum și proprietatea Active a fiecărei componente ADODataSet. Când utilizatorul se întoarce din călătorie, trebuie să introducă informații despre modificările pe care le-a făcut în baza de date. Pentru a face acest lucru, trebuie să încărcați date din fișierele locale, să conectați seturile de date la baza de date și să apelați metoda UpdateBatch.

Câteva cuvinte despre ADO.NET

ADO.NET face parte din noua arhitectură .NET dezvoltată de Microsoft. Arhitectura .NET este încercarea Microsoft de a reproiecta instrumentele și instrumentele de dezvoltare software pentru a le face mai convenabile pentru crearea de aplicații web. ADO.NET este o nouă dezvoltare a ADO, axată pe rezolvarea problemelor asociate cu dezvoltarea sistemelor web și eliminarea multor deficiențe ale tehnologiei ADO învechite. Problema cu ADO este că este o tehnologie bazată pe COM. Pentru aplicațiile cu unul și două niveluri, COM este o platformă perfect acceptabilă, dar în lumea Web-ului, utilizarea COM ca mecanism de transport este practic imposibilă. Există trei probleme principale cu COM care limitează utilizarea sa pe Web: în primul rând, COM funcționează doar într-un mediu Windows, în al doilea rând, transferul seturi de înregistrări necesită marshaling COM și, în al treilea rând, apelurile COM nu pot pătrunde în firewall-urile corporative. Tehnologia ADO.NET rezolvă toate cele trei probleme prin utilizarea XML.
O altă caracteristică a ADO.NET este separarea setării de înregistrări ADO tradiționale în mai multe clase separate. În loc să rezolve multe probleme, fiecare clasă este concepută pentru a rezolva o problemă specifică. De exemplu, ADO.NET are o clasă DataSetReader care oferă acces numai în citire la date în modul Forward-only, datele fiind situate pe partea serverului. Datorită tuturor acestor restricții, această clasă oferă citirea rapidă a setului de date rezultat. Clasa DataTable funcționează ca un set de înregistrări dezactivat pe partea clientului. Clasa DataRelation împărtășește caracteristici comune cu furnizorul MSDataShape OLE DB. În orice caz, cunoștințele despre tehnologia tradițională ADO vor fi extrem de utile atunci când învățați noua tehnologie ADO.NET.

În acest capitol, am analizat tehnologia ADO (ActiveX Data Objects) și dbGo, un set de componente Delphi concepute pentru a accesa interfețele ADO. Ați învățat cum să lucrați cu MDAC (Microsoft Data Access Components) și diverse mecanisme de accesare a serverelor de baze de date. V-am povestit despre avantajele și dezavantajele tehnologiei ADO.
Capitolul 16 prezintă arhitectura DataSnap încorporată a Delphi, care vă permite să dezvoltați aplicații client și server pe trei niveluri. Totuși, această problemă poate fi rezolvată folosind ADO această carte este în primul rând despre Delphi, așa că vă voi spune despre o soluție la problema care este firească pentru Mediile Delphi. Odată ce am terminat de analizat DataSnap, vom continua să explorăm arhitectura de date încorporată a Delphi. În capitolul 17, vom analiza procesul de dezvoltare a propriilor componente de date.

Evenimentul are loc înainte ca comanda să fie executată. Opțiuni:
  • Sursa este un șir care conține instrucțiunea SQL sau numele procedurii stocate.
  • CursorType - tipul de cursor pentru Recordset-ul care va fi deschis. Tipul de cursor poate fi schimbat. Valori posibile:
    • adOpenUnspecified(-1) - tipul cursorului este nespecificat.
    • adOpenForwardOnly(0) - definește un cursor numai înainte. La fel ca un cursor static, dar puteți derula înainte numai prin intrări. Acest lucru optimizează execuția dacă trebuie să faceți o singură trecere prin Recordset.
    • adOpenKeyset(1) - Definește un cursor de set de taste. La fel ca un cursor dinamic, dar nu puteți vedea înregistrările adăugate de alți utilizatori, deși înregistrările șterse de alți utilizatori nu sunt disponibile în setul dvs. de înregistrări. Modificările aduse datelor de către alți utilizatori sunt vizibile.
    • adOpenDynamic(2) - Definește un cursor dinamic. Adăugările, modificările și ștergerile de către alți utilizatori sunt vizibile; Sunt permise toate tipurile de mișcare prin Recordset, cu excepția marcajelor dacă furnizorul nu le acceptă.
    • adOpenStatic(3) - Definește un cursor static. O copie statică a unui set de înregistrări pe care o puteți folosi pentru a găsi date sau a genera rapoarte. Adăugările, modificările sau ștergerile de către alți utilizatori nu sunt vizibile.
  • LockType - tipul de blocare pentru Recordset care va fi deschis. Valori posibile:
    • adLockUnspecified(-1) - tipul de blocare este nespecificat.
    • adLockReadOnly(1) - numai pentru citire. Nu puteți modifica datele.
    • adLockPessimistic(2) - blocare pesimistă. Furnizorul garantează editarea cu succes a înregistrărilor. Înregistrarea este blocată imediat după începerea editării și până când înregistrările sunt salvate.
    • adLockOptimistic(3) - blocare optimistă. Furnizorul blochează înregistrările numai atunci când modificările sunt salvate, de exemplu. când apelați metoda Update().
    • adLockBatchOptimistic(4) - modificări optimiste ale loturilor. Necesar pentru modul de modificare a lotului (salvare întârziată a înregistrărilor).
  • Opțiuni - un număr întreg (lung) care indică opțiuni pentru executarea unei comenzi sau deschiderea unui Recordset.
  • adStatus - determină starea evenimentului. Valori posibile - consultați descrierea unui parametru similar al evenimentului ConnectComplete.
  • pCommand este obiectul de comandă pentru care se aplică acest eveniment.
  • pRecordset este obiectul Recordset pentru care se aplică acest eveniment.
  • pConnection este obiectul Connection pentru care se aplică acest eveniment.
Evenimentul WillExecute poate apărea din cauza apelurilor către Connection.Execute, Command.Execute sau Recordset.Open. Parametrul pConnection conține întotdeauna o referință la obiectul Connection. Dacă evenimentul are loc din cauza unui apel către Connection.Execute, parametrii pRecordset și pCommand vor fi setați la Nimic. Dacă evenimentul are loc din cauza unui apel către Recordset.Open, parametrul pRecordset va conține o referință la obiectul Recordset, iar parametrul pCommand va fi setat la Nimic. Dacă evenimentul are loc din cauza unui apel către Command.Execute, parametrul pCommand va conține o referință la obiectul Command, iar parametrul pRecordset va fi setat la Nimic.

Odată ce cunoașteți elementele de bază ale lucrului cu ADO, puteți trece la scrierea de programe pentru a lucra cu ADO în aplicații. Vom folosi din nou ADO pentru a ne conecta la baza de date Biblio.mdb, dar acest lucru va fi suficient pentru demonstrație principii generale. Să începem cu următorul exemplu și apoi să trecem la programare:

1. Creați un nou proiect cu comanda File > Proiect nou. Selectați pictograma EXE standard în caseta de dialog Proiect nou și faceți clic pe OK.

2. Setați proprietatea Nume a proiectului la ADORecordset.

3. Setați proprietatea Name a Form1 la frmMain și proprietatea Caption la Working with ADO Recordsets.

4. Creați o listă în formularul frmMain și setați-i proprietatea Name la 1st Authors.

După cum am menționat mai devreme, un element de date ADO este un control ActiveX. Poate fi tras pe formular ca orice alt element. Obiectele Connection și Recordset sunt DLL-uri active (Dynamic Link Libraries) și pot fi accesate numai prin referire la biblioteca de tipuri.

NOTĂ Biblioteca de tipuri conține o descriere completă a componentei: proprietăți, metode, evenimente și tipuri de date.

5. Rulați comanda Proiect în Visual Basic > Referințe pentru a deschide caseta de dialog Referințe.

8. Adăugați următoarele declarații la secțiunea (General) (Declarații) a formularului:

Private cn As ADODB.Connection

Private rs As ADODB.Recordset

9. Introduceți următorul fragment în procedura de eveniment Form_Load:

Private Sub Form_Load()

Dim cmd As String

Dim sql As String

Dim cn As ADODB.Connection

Dim rs As ADODB.Recordset

„Creează șirul de conexiune

cmd = "Furnizor=microsoft.jet.OLEDB.3.51"" & _

„Sursa de date=" & _

„C:\Program Files\Microsoft Visual Studio” & _

„\VB98\Biblio.mdb”

„Stabiliți o conexiune la baza de date

Set cn = New ADODB.Connection

ConnectionString = cmd

„Creați o cerere

sql = „selectați * din autori”

„Deschideți setul de înregistrări

Set rs.= Nou ADODB.Recordset

Faceți când nu rs.EOF


„Săriți la următoarea intrare

„Închideți setul de înregistrări.

Set rs = Nimic

„Conexiune strânsă

„distruge obiectul conexiunii

Set cn = Nimic

10.Salvați și rulați proiectul.

Programul accesează pur și simplu baza de date Biblio.mdb și populează lista cu numele autorilor din tabelul Authors. Probabil vei crede că programul este prea mare pentru o sarcină atât de simplă, dar dacă te uiți cu atenție, vei înțelege că nu este nimic complicat în el.

La începutul programului sunt declarate două variabile, cmd și sql. Variabila cmd va stoca șirul de conexiune ADO folosit pentru a se conecta la baza de date. Variabila sql este pentru textul interogării SQL. Următorul fragment creează o linie pentru a se conecta la Biblio.mdb utilizând noul furnizor OLEDB (specificat după Provider = construct la începutul liniei). Dacă trebuie să vă conectați la un alt tip de sursă de date, de exemplu, SQL Server, specificați un alt furnizor. Al doilea parametru șir specifică numele bazei de date. Șirul de conexiune ADO face toate sarcinile grele, așa că ar trebui să fie obiectivul dvs. principal. Evidențierea acestui cod în functie separata vă permite să creați diverse coarde conexiuni pentru lucrul cu diferite baze de date (de exemplu, Access, SQL Server și Oracle). Puteți transmite un parametru unei astfel de funcție, care este folosit pentru a construi un șir de conexiune unic. Acest lucru va simplifica procesul de migrare a aplicațiilor dvs. compatibile ADO către alte surse de date.

Urmatorul pas- conexiune efectivă la baza de date. Pentru a face acest lucru, creăm un obiect ADO.Connection și apoi setăm proprietatea ConnectionString la cmd. După aceasta, metoda este executată. Deschide acest obiect. Metoda preia datele găsite în proprietatea ConnectionString și le folosește pentru a se conecta la baza de date.

După stabilirea unei conexiuni la baza de date, deschidem obiectul ADO. Set de înregistrări pentru primirea înregistrărilor. Cu toate acestea, trebuie mai întâi să îi transmiteți o interogare SQL care identifică înregistrările pe care le doriți. În programul nostru, următoarea linie face acest lucru:

sql = „selectați * din autori”

Fără a intra în prea multe detalii SQL, ceea ce înseamnă această interogare este: „selectați toate înregistrările (*) din tabelul numit Autori”. Este exact ceea ce s-a făcut în exemplul nostru.

Avem o interogare care poate fi folosită pentru a crea un set de înregistrări. Un nou obiect set de înregistrări este creat după cum urmează:

Set rs = ADODB.Recordset nou

Setul nou creat nu conține nicio informație. În blocul With îi spunem ADO să deschidă setul cu comanda

Deschideți sql, cn, adOpenForwardOnly, adLockReadOnly

Probabil ați observat parametrii necesari pentru a deschide un set de înregistrări. Primul parametru stochează interogarea SQL pentru acest set. Al doilea parametru, cn, specifică faptul că setul ar trebui să folosească obiectul de conexiune cn pentru a se conecta la baza de date. Se poate face o analogie între un set de înregistrări și o mașină: o conexiune este drumul pe care mașina ajunge la date. Următorul parametru îi spune ADO ce tip de cursor al bazei de date ar trebui utilizat pentru set. Următorul tabel listează opțiuni posibile cursore cu descrieri scurte.

Tip cursor Descriere
adOpenForwardOnly Un cursor de acest tip poate fi folosit doar pentru a itera secvențial prin înregistrări într-o singură direcție. Cauta in direcție inversă iar tranzițiile arbitrare nu sunt permise. Cu toate acestea, această opțiune este rapidă și utilă dacă trebuie să completați rapid o listă sau o casetă combinată
Ad0penKeyset Tipul de cursor optim pentru seturi mari. Nu primiți notificări despre modificările datelor care v-ar putea afecta setul de înregistrări
Ad0penDynamic Cursorul vă permite să urmăriți toate modificările pe care alți utilizatori le fac setului dvs. de înregistrări. Are cele mai multe capacități, dar din această cauză funcționează mai lent decât toate celelalte
AdOpenStatic Cursorul static este util pentru seturi mici

În cele din urmă, ultimul parametru îi spune ADO că setul de înregistrări va fi doar pentru citire. În schimb, puteți specifica un alt pe-zimlock din următorul tabel, cu toate acestea, în exemplul nostru, a fost aleasă cea mai rapidă opțiune.

Dacă toți parametrii au fost specificați corect, setul de înregistrări se deschide și puteți lucra cu datele acestuia.

În fragmentul următor, programul parcurge toate înregistrările până când este găsit un indicator de sfârșit de fișier (EOF). Când mutam cursorul la următoarea înregistrare, introducem datele din câmpul Autor în listă:

lstAuthors.AddItem rs(„Autor”)

După adăugarea următoarei nume în listă, trecem la următoarea intrare folosind metoda. Mutați Următorul. Dacă uitați de acest lucru, bucla va rula pentru totdeauna, deoarece sfârșitul fișierului nu va fi niciodată atins. În cele din urmă, după terminarea lucrării, totul deschis trebuie închis, iar tot ce este creat trebuie distrus. Pentru a face acest lucru, apelați metoda .Close pe obiectele Recordset și Connection. Aceste obiecte li se atribuie apoi Nimic pentru a preveni scurgerile de memorie în aplicația dvs.

ATENŢIE Când procesați intrările setului într-o buclă, asigurați-vă că includeți o metodă în buclă. Mutați Următorul. Dacă uitați să faceți acest lucru (și acest lucru se întâmplă des), programul dvs. va intra într-o buclă. Scrieți instrucțiunea Do While... și apoi comanda .MoveNext imediat înainte de comanda Loop și abia apoi introduceți codul de procesare a datelor. Astfel reduceți probabilitatea de eroare la minimum.

Adăugarea de intrări

Deși această caracteristică nu a fost necesară în acest exemplu, majoritatea aplicațiilor adaugă înregistrări noi la seturi. Cu obiectele ADO Recordset, această sarcină este extrem de ușoară. Pentru a face acest lucru, programul ar trebui să apeleze metoda.AddNew:

rs("Author) = "Doe, John" rs("Au_ID") = 123456

Totul este foarte simplu. Când trebuie să creați o intrare nouă, apelați metoda .AddNew. Acesta creează o înregistrare goală, care este apoi umplută cu date. Acest lucru se poate face în mai multe moduri, inclusiv următoarele:

Rs(„Autor”) = „Doe, John”

Rs!Autor = „Doe, John”

Rs.Fields(1) = „Doe, John”

Toate sunt echivalente și alegerea depinde de gustul tău personal. Personal, prefer prima metodă pentru că pare cea mai evidentă. Știu exact ce câmp este actualizat și, deoarece numele câmpului este între ghilimele, poate conține spații.

După introducerea datelor într-o înregistrare, ar trebui să actualizați setul apelând metoda. Actualizați.

Actualizarea înregistrărilor

Procesul de actualizare a înregistrărilor este similar cu procesul de adăugare, dar de data aceasta nu trebuie să apelați metoda .AddNew. Este suficient să mutați cursorul bazei de date la înregistrarea dorită, să schimbați datele și să apelați metoda. Actualizați. De exemplu:

Rs(„Autor”) = „Maro, Steve”

Rs(„Au_ID”) = 373737

NOTĂ Dacă ați lucrat vreodată cu obiecte DAO, este posibil să fiți obișnuit să apelați o metodă. Editați pentru a trece la editarea datelor. Nu este acceptat de obiectele ADO.

Ștergerea intrărilor

Ștergerea înregistrărilor este la fel de ușoară în ADO. Tot ce trebuie să faceți este să setați cursorul bazei de date pe înregistrarea care urmează să fie ștearsă și să apelați metoda. Șterge. Programul arată cam așa:

„Creează cerere

sql = „selectați *din autori unde = „Maro, Steve””

„Deschideți setul de înregistrări

Set rs = ADODB.Recordset nou

Deschideți sql, cn, adOpenForwardOnly, adLockReadOnly

Dacă rs.RecordCount > 0, atunci

„Închideți setul de înregistrări

„Distrugeți un obiect set de înregistrări

Set rs = Nimic

CHEIE Treceți la utilizarea ADO, deoarece Microsoft își dezvoltă tehnologiile de date în această direcție. Nu numai că veți lucra cu cea mai recentă tehnologie, dar veți putea, de asemenea, să vă portați aplicațiile către alte surse de date cu modificări minime (sau deloc) de cod. În plus, ADO vă permite chiar să faceți schimb de date între baza de date și Web. pagină!

Acum știți cum să creați baze de date Access și să lucrați cu ele într-o varietate de moduri. Abilitățile abordate în această lecție vă vor ajuta să lucrați cu baze de date în aplicațiile viitoare. Deși capacitățile noii versiuni de Visual Data Manager au crescut semnificativ, aș recomanda totuși achiziționarea Microsoft Access dacă nu ați făcut acest lucru înainte. Accesul are multe caracteristici care fac crearea unei baze de date mai ușoară chiar și chiar și procesul simplu descris mai sus. Cea mai bună parte este că bazele de date vor rămâne compatibile cu Visual Basic!

Odată ce învățați cum să lucrați cu fișiere și baze de date, puteți prelua date din aplicația dvs. și le puteți salva pentru descărcare sau imprimare ulterioară și le puteți utiliza pentru a salva și a prelua parametrii de funcționare a aplicației. Fă-ți timp pentru a experimenta cu Visual Data Manager. Are multe caracteristici care nu au fost menționate în acest tutorial (o descriere completă ar necesita o carte separată). Combinând capacitățile de programare și baze de date ale Visual Basic, puteți crea aplicații puternice. Următoarea lecție se concentrează pe al treilea aspect important al oricărei aplicații - imprimarea.

Adnotare: În această prelegere vom vorbi despre mecanismele de acces la date BDE și ADO și vom discuta avantajele și dezavantajele acestora. Să creăm o bază de date folosind MS Access. Apoi vom crea o aplicație care funcționează cu această bază de date folosind mecanismul ADO.

De la apariția tehnologiei bazelor de date, programatorii au avut nevoie de mecanisme pentru a accesa tocmai aceste date. Diverse companiiîn felul lor au încercat să le ofere o asemenea oportunitate. De exemplu, pentru a lucra cu tabele de tip dBase, un sistem de management al bazelor de date ( SGBD) Maşină de tuns. Pentru vremurile sistemului de operare, MS-DOS este o soluție excelentă. in orice caz Maşină de tuns nu a putut funcționa cu alte tipuri de tabele. Și cu cât au apărut mai multe tipuri de date, cu atât a apărut mai urgentă necesitatea dezvoltării unui instrument de acces universal care să poată funcționa cu orice tip de date.

Mecanismul de acces la date este un instrument software care vă permite să accesați o bază de date și tabelele acesteia. De regulă, acesta este un driver sub formă de fișiere *.dll, care este instalat pe computerul dezvoltatorului (și al clientului) și care este utilizat de program pentru a comunica cu baza de date.

Comparație între BDE și ADO

Motor de bază de date Borland (BDE)- prima astfel de dezvoltare de la Borland. Acest mecanism de acces la date permite accesul la formatele de baze de date locale și server de fișiere dBase, FoxPro și Paradox, la diverse Servere SQLși la multe alte surse de date, accesul la care a fost acceptat folosind drivere ODBC. De exemplu, folosind BDE Puteți lucra direct cu fișiere de foi de calcul MS Excel. Din păcate, mecanismul de acces BDE considerat învechit chiar de Borland însuși. ÎN acest moment Multe instrumente Delphi sunt multiplatforme, adică programele cu modificări minore pot fi transferate pe alte sisteme de operare. Borland Corporation a lansat un nou mediu de dezvoltare rapidă a software-ului - Kylix, care creează aplicații pentru sistemele de operare Familia Linux. Se spune adesea că Kylix este Delphi pentru Linux. Așa este - dacă poți programa în Delphi, poți programa și în Kylix. Majoritatea instrumentelor Delphi au fost moștenite de la Kylix, dar, din păcate, nu BDE. Dezvoltare în continuare acest mecanism de acces la dateîntrerupt de Borland Corporation.

Cu toate acestea, este prea devreme pentru a-l îngropa. Mulți programatori încă folosesc acest instrument pentru a dezvolta aplicații pentru companii mici. Ce să spun, compania chineză Huawei, care dezvoltă cele mai noi PBX-uri electronice atât pentru telefoane fixe, cât și pentru telefoane mobile, folosește în continuare BDE pentru a accesa setările și statisticile acestor PBX-uri! In afara de asta, BDE are multe caracteristici simple și convenabile pentru programator, cum ar fi crearea tabelelor în mod programatic.

Ușurință în utilizare BDE Este greu de supraestimat, dar nu se poate să nu menționăm dezavantajele. Principalul dezavantaj este distribuția aplicațiilor. Dacă aplicația dvs. folosește componente pentru a accesa date BDE, atunci clientul care va utiliza programul dvs. trebuie să îl aibă instalat BDE. Mai mult, dacă ați folosit alias-uri (alias-uri baze de date), atunci clientul ar trebui să fie configurat și pentru aceleași alias-uri. Cu toate acestea, crearea unui pachet de instalare folosind utilitarul de instalare standard Shield Express elimină această problemă. Acest utilitar vă permite să activați mecanismul configurat BDE incluse în pachetul de instalare al programului dvs. Desigur, trebuie să plătiți pentru asta cu dimensiuni mari ale fișierelor de instalare.

Un alt dezavantaj se referă nu numai la BDE, dar și orice alt universal mecanism de acces la date. Universalitatea unui astfel de mecanism implică complexitatea implementării lui. Programatorul este prevăzut cu un instrument gata făcut, cu care este convenabil să lucrați, dar acest instrument este destul de „greu” - folosindu-l, creșteți destul de semnificativ dimensiunea aplicației dvs.

În cursul anterior „Introducere în programare în Delphi” am atins lucrul cu bazele de date folosind BDE. Nu vom mai reveni la aceste subiecte, deși ocazional ne vom referi BDE pentru a demonstra anumite capabilități care nu sunt disponibile în alte mecanisme de acces la date sau care diferă de acestea. Prin urmare, dacă ați ratat acest curs, atunci revizuiți cel puțin pe scurt munca cu BDEîn prelegerile 29-32.

Obiect de date ActiveX (ADO)- Acest mecanism de acces la date, dezvoltat de Microsoft Corporation. Pentru a fi mai precis, atunci ZGOMOT- acesta este un supliment la tehnologie OLE DB, prin care puteți comunica cu diverse date aplicației Microsoft. La mijlocul anilor 1990, tehnologia s-a dezvoltat foarte mult COM, iar Microsoft Corporation a anunțat, prin urmare, o tranziție treptată de la tehnologie veche ODBC la unul nou OLE DB. Cu toate acestea, tehnologia OLE DB destul de complex, utilizarea acestei tehnologii are loc la nivel de sistem și necesită multe cunoștințe și muncă din partea programatorului. În plus, tehnologie OLE DB foarte sensibil la erori și se blochează cu prima ocazie. Pentru a ușura viața programatorilor, Microsoft a dezvoltat un alt program strat de aplicație ZGOMOT pe care le vom studia în acest curs.

În funcție de capacitățile tale ZGOMOT amintește BDE, deși desigur, este mai mult Unealtă puternică. Borland a dezvoltat un set de componente de acces ZGOMOTși a numit-o inițial ADOExpress. Cu toate acestea, Microsoft se opune cu încăpățânare utilizării denumirilor sale în produsele terțe, prin urmare, începând cu Delphi 6, acest set de componente a început să fie numit dbGo. Puteți vedea aceste componente în fila ADO palete componente.

Tehnologie ZGOMOT, ca BDE, independent de un anumit server de baze de date, are suport atât pentru baze de date locale de diferite tipuri, cât și pentru unele baze de date client-server. Această tehnologie are multe avantaje. Driverele dezvoltate de Microsoft pentru uz propriu sunt mai fiabile decât driverele producători terți. Prin urmare, dacă trebuie să lucrați cu baze de date MS Access sau pentru arhitectura client-server utilizați MS SQL Server, apoi utilizați ZGOMOT va fi cel mai de preferat. În plus, există un plus în materie de distribuție a programelor - toate Windows-urile moderne au drivere încorporate ZGOMOT. Cu alte cuvinte, programul dumneavoastră va rula pe orice PC cu Windows instalat.

În mod ciudat, principalul dezavantaj constă și în problema distribuției programelor. Microsoft face ceva destul de inteligent. La fiecare doi ani apar versiuni noi de Windows. De obicei, utilizatorul obișnuit nu are nevoie să treacă la un nou sistem de operare, mai ales că fiecare sistem nou devine din ce în ce mai solicitant cu resursele computerului. Pentru a forța utilizatorul să meargă la versiune noua, Microsoft este sigur că va introduce câteva standarde sau tehnologii noi care sunt incompatibile cu cele vechi. Și pentru versiunile mai vechi nu sunt furnizate îmbunătățiri. Așa că bietul utilizator trebuie să strângă din dinți și să cheltuiască bani pe versiuni noi ale sistemului de operare și pachetului MS Office. Prin urmare, atunci când utilizați tehnologia ZGOMOT trebuie să te gândești ce versiune de Windows ai Utilizator final dacă programul tău va funcționa pe computerul lui.

Tehnologie ZGOMOT face parte de fapt Componente de acces la date Microsoft (MDAC). Microsoft distribuie MDAC ca produs separat, din fericire gratuit. Cu toate acestea, doar cea mai recentă versiune este acceptată MDAC. De exemplu, Delphi 7 include MDAC 2.6. Când distribuiți propriile programe, ar trebui să țineți cont de faptul că, cel mai probabil, clientul are deja instalat același software. MDAC, și majoritatea ultima versiune. Cu toate acestea, dacă folosește versiuni mai vechi de Windows (Win95, 98, ME, NT), atunci va trebui să vă ocupați de instalare. MDAC la computerul lui. Dacă are instalat Win2000, WinXP sau un sistem de operare mai nou, atunci MDAC el o are deja și nu ai de ce să-ți faci griji.

Un alt minus serios ZGOMOT Problema este că folosește tehnologia COM destul de lentă pentru a se conecta la baza de date. Dacă baza de date conține câteva mii de înregistrări, atunci viteza de lucru cu tabele poate deveni de sute de ori mai lentă decât dacă ați folosi BDE! Pe computerele moderne cu frecvențe de procesor de până la 2 GHz și mai mari, este posibil ca aceste încetiniri să nu fie vizibile, dar lucrând cu bază imensă datele de pe computere mai lente se vor transforma într-o așteptare completă.

Principalele componente cu care trebuie să lucrăm sunt TADOConnection (pentru conectarea la baza de date), TADOTable (analogic TTtable din BDE), TADOQuery (analogic TQuery din BDE, pentru executarea de interogări și preluarea unui set de date) și TADODataSet (destinat unui set de date obținut printr-o interogare SQL).

Crearea unei baze de date MS Access

Bază de date MS Access au multe avantaje, programatorii preferă adesea să le folosească. În primul rând, baza de date MS Access- acesta este un singur fișier. Indiferent de câte tabele și indici conține, totul este stocat într-un singur fișier. Aceasta înseamnă că o astfel de bază de date este mai ușor de întreținut - transferați într-o nouă locație, faceți copii de rezervăși așa mai departe. Un alt plus este că numele câmpurilor dintr-o astfel de bază de date pot fi date cu litere rusești.

Cel mai bun mod de a învăța materiale noi este prin practică. De exemplu, să creăm o bază de date pentru departamentul de personal al unei întreprinderi. De ce date angajaților avem nevoie? În primul rând, numele de familie, prenumele și patronimul. Apoi indicați sexul (masculin sau feminin), Statusul familiei(necăsătorit sau căsătorit), numărul de copii. De asemenea, veți avea nevoie de data nașterii și de data intrării în muncă. Experiență de muncă în ani. Educaţie. Recruit sau nu. Numere de telefon la care puteți contacta un angajat în orice moment. Funcția și departamentul (dacă există) al angajatului în care este înregistrat. Și, de asemenea, adresa lui de acasă. Totodata, tinem cont de faptul ca angajatul nu este neaparat rezident al orasului in care lucreaza. Dacă ar veni să lucreze din alt oraș? Sau chiar din alta tara? În consecință, va trebui să intri atât în ​​țară, cât și în oraș - ce se întâmplă dacă trebuie să faci un raport asupra angajaților înregistrați în Ucraina, de exemplu? Cam atât vor trebui introduse date pentru departamentul HR! Dar le-am simplificat puțin mai mult. Experiența de lucru este împărțită în generală și continuă. Aceste date sunt luate în considerare la calcularea concediului medical. Dar pentru o bază de date de antrenament, astfel de detalii pot fi neglijate.

Deci, în primul rând, optimizăm datele pe baza regulilor lui trei forme normale. Ca rezultat, obținem patru tabele:


Orez. 2.1.

Tabelul principal aici va fi LichData, care conține date de bază despre angajat. Are conexiuni relaționale cu alte tabele. Câmpul „Cheie” se va incrementa automat, adică va fi adăugat automat câte unul, garantându-ne unicitatea cheii. ÎN mesele subordonate există un câmp „Angajat” de un întreg tip care va fi folosit pentru a furniza comunicare. În plus, câmpurile cheie în mese pentru copii Nu va fi.

Masa principală menține o relație unu-la-unu cu Doljnost și Adrese, și o relație unu-la-mulți cu masa Telefoane, pentru că probabil angajatul are atât telefoane de acasă, cât și de serviciu și poate are câteva telefoane mobile în buzunare. Adică un angajat poate avea mai multe telefoane.

Acum că ne-am hotărât asupra câmpurilor și conexiunilor, este timpul să creăm o bază de date. Pentru a face acest lucru, descărcați programul MS Access.

Dacă nu aveți panoul „File Creation” în partea dreaptă a ferestrei, atunci selectați comanda „File - New”. Apoi selectați comanda New Database. Va apărea imediat un prompt cu numele acestei baze de date. Creați un folder de care vom avea în continuare nevoie pentru noul proiect, specificați acest folder și denumiți baza de date ok (departamentul HR). După ce faceți clic pe butonul „Creați”, va apărea această fereastră de bază de date:


Orez. 2.2.

Acum trebuie să facem patru tabele. Prin urmare, faceți dublu clic pe comanda „Creați tabel în modul design” și mergeți la designer. În partea stângă introducem numele câmpului și cu litere rusești. În câmpul „Tipul de date”, selectați tipul, iar în fila „General”, efectuați setările câmpului. Descrierea câmpului este opțională. Deci, să creăm câmpurile:

  1. "Cheie". Desigur, scriem numele câmpului fără ghilimele. Selectăm tipul de date „Contor”, acesta este un tip de date cu incrementare automată. În setări, asigurați-vă că câmpul este indexat - Da (coincidențele nu sunt permise). Faceți clic dreapta pe acest câmp și selectați Câmp cheie. O pictogramă cheie va apărea în stânga câmpului.
  2. "Nume de familie". Tipul câmpului este text, dimensiunea 25 de caractere. Câmp indexat - Da (potriviri permise). La urma urmei, rudele sau omonimii ar putea fi prinși!
  3. "Nume". Tipul câmpului este text, dimensiunea 25 de caractere. Câmp indexat - Da (potriviri permise).
  4. "Nume de familie". Tipul câmpului este text, dimensiunea 25 de caractere. Nu sunt necesare indexuri.
  5. "Podea". Text, dimensiune 3 caractere. În formatul câmpului, indicați „soț/soții”, bineînțeles, fără ghilimele.
  6. „Sem_Pozh”. Tip boolean, format câmp „Da/Nu”. Aici vom indica dacă angajatul este căsătorit.
  7. „Copii”. Tip numeric, dimensiune câmp Bytes (este greu de imaginat că cineva ar avea mai mult de 255 de copii!).
  8. "Data nașterii". Tip câmp - Data/Ora. Selectați formatul de dată scurtă. Apoi alegeți același format pentru câmpul Mască. Când încercați să selectați o mască, vi se va cere să confirmați salvarea tabelului. Răspundeți afirmativ și, în loc de numele tabelului implicit „Tabelul 1”, introduceți „LichData”, acesta va fi numele primului nostru tabel. După aceasta, va apărea fereastra pentru crearea unei măști de intrare. Selectați „Short Date Format”, faceți clic pe „Next”, apoi introduceți „00.00.0000” în fereastra „Input Mask”. Ca urmare, vom avea o mască sub forma „zz.ll.aaaa”.
  9. „Date_Post”. Totul este la fel ca la nr. 8.
  10. "Experienţă". Tipul câmpului este numeric, dimensiunea este octeți.
  11. "Educaţie". Text, dimensiunea câmpului 30 de caractere. La urma urmei, poate exista un text lung aici, de exemplu, „învățământ tehnic superior neterminat”.
  12. „Conscris” Tip boolean, format Da/Nu.

Drept urmare, obținem următoarea imagine.

Erori

Obiect ADO.Connection, conectarea la o bază de date din VBScript, proprietatea ConnectionString, generarea unui șir de conexiune OLE DB folosind un fișier UDL, gestionarea erorilor la conectarea la o bază de date, colecția de erori

Crearea unui obiect Connection este foarte simplă. De exemplu, pentru a vă conecta la baza de date Northwind pe un server SQL numit LONDRA, puteți utiliza cod ca

Dim cn

cn.Provider = "SQLOLEDB"

& „InițialCatalog= vânt de nord"

cn.Deschis

În principiu, acest lucru este suficient pentru a crea un obiect de conexiune de lucru (pentru a verifica acest lucru, puteți, de exemplu, să rulați comanda Wscript.Ecoucn.Stat înainte și după deschidere). Cu toate acestea, este logic să vorbim mai detaliat despre diferitele proprietăți și metode ale acestui obiect.

proprietate Furnizor definește driverul care va fi utilizat pentru conectarea la baza de date. Există două tipuri de drivere de conexiune utilizate în mod obișnuit - drivere OLE DB și ODBC. Dacă este posibil, ar trebui să utilizați o conexiune OLE DB - o metodă mai modernă care funcționează mult mai rapid. Proprietatea Provider trebuie specificată numai atunci când se conectează prin OLE DB; când se conectează prin ODBC, toți parametrii necesari sunt trecuți folosind proprietatea ConnectionString. Valorile proprietăților furnizorului pentru conectarea la diferite surse de date pot arăta astfel:

o „Microsoft .Jet .OLEDB .4.0” - pentru conexiuni la fișiere Access și Excel și alte surse de date bazate pe Jet;

o „SQLOLEDB” - pentru conexiuni la SQL Server (ca în exemplu)

o "MSDAORA .1" - pentru conexiuni la serverul Oracle;

o „ADsDSOObject” - pentru a se conecta la baza de date Windows Directory Service.

proprietate ConnectionString- proprietatea principală a obiectului Connection. Definește parametrii pentru conectarea la sursă (valoarea acestuia este un set de parametri separați prin punct și virgulă, ordinea semnificației lor nu contează). În exemplul nostru, am trecut patru valori ale parametrilor - ID utilizator - ID utilizator (aceasta înseamnă că folosim o conexiune SQL Server), Parolă - parolă și Sursă de date - numele serverului bazei de date, Catalog inițial - numele baza de date de pe acest server. Pentru a trece un ConnectionString, puteți folosi și metoda Deschis. Dacă am folosi o conexiune Windows la SQL Server, codul de conexiune ar putea arăta astfel:

Dim cn

Set cn = CreateObject("ADODB.Connection")

cn.Open "Provider=SQLOLEDB; Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=Northwind;Data Source=london1"

Când vă conectați la un fișier Access sau Excel, șirul de conexiune poate arăta astfel:

cn.Deschideți „Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\Borey.mdb”

Cel mai simplu mod de a crea un șir de conexiune este să utilizați un fișier UDL. Pentru a face acest lucru, trebuie să creați un fișier text obișnuit, să-l redenumiți astfel încât extensia sa să arate ca .udl (din linkul de date utilizator), să faceți dublu clic și să configurați parametrii de conexiune. Apoi puteți deschide acest fișier în Notepad și copiați linia generată. De asemenea, puteți utiliza un link către fișierul UDL creat în șirul de conexiune:

cn.ConnectionString = „Nume fișier = d:\mylink.udl”

Această metodă este mai recomandată (mai ales dacă fișierele UDL sunt situate într-un director de rețea ascuns doar pentru citire) deoarece permite ca modificările să fie făcute central în toate aplicațiile dacă sursa de date se mută pe un alt server.

Pentru a vă conecta prin ODBC, este recomandat să creați mai întâi o sursă de date ODBC (prin Panoul de control -> Surse de date (ODBC), apoi să generați un șir de conexiune în același mod folosind un fișier UDL, selectând Microsoft OLE DB Provider pentru ODBC Șofer șoferi.

· metoda Deschis vă permite să deschideți o conexiune la baza de date (și să verificați funcționalitatea acesteia). Poate lua ca parametri un șir de conexiune, un nume de utilizator și o parolă.

· metoda Închide vă permite să închideți conexiunea (obiectul de conexiune nu este șters din memorie). Pentru a scăpa complet de acest obiect, puteți folosi codul

cn.Închidere

Set cn = Nimic

sau pur și simplu A stabilitcn= Nimic - conexiunea va fi deconectată automat.

Există multe alte proprietăți și metode disponibile pentru acest obiect, dar acestea nu vor fi acoperite aici (consultați documentația Microsoft sau cursurile de formare pentru mai multe informații). Singura proprietate pe care trebuie să o luați în considerare este proprietatea Errors, care returnează o colecție de obiecte Error. Erorile la configurarea sau operarea unei conexiuni apar foarte des (parola sau numele de utilizator au fost introduse incorect, utilizatorul nu are suficiente drepturi de conectare, este imposibil să acceseze computerul prin rețea etc.), deci este puternic recomandat pentru a implementa gestionarea erorilor în program. Cel mai simplu mod de a implementa un handler de erori ar putea arăta astfel:

Dimcn

Set cn = CreateObject("ADODB.Connection")

cn.Provider = "SQLOLEDB"

cn.ConnectionString = "ID utilizator=SA;Parolă=parolă;Sursa datelor = LONDRA1;" _

& „Catalog inițial = Northwind”

La eroare GoTo CnErrorHandler

cn.Deschis

Ieșiți din sub

CnErrorHandler:

Pentru fiecare ADOErr În cn.Erori

Debug.Print ADOErr.Number

Debug.Print ADOErr.Description

Următorul

SfârşitSub

În practică, erori tipice pentru a acestei conexiuni(Nu Fișier de acces, eroare de parolă sau nume de utilizator la conectarea la SQL Server, fără drepturi, fișier deschis în modul exclusiv etc.). iar utilizatorului i se cere să corecteze eroarea.

Cele mai importante proprietăți ale obiectului ADOError:

· Descriere- descrierea erorii. De obicei cel mai mult Informații importante este cuprinsă exact în descriere.

· Număr- numărul erorii. Este convenabil să căutați după număr în baza de cunoștințe și pe Internet.

· Sursă- sursa erorii. Aceste informații sunt utile numai dacă colecția Erori poate conține erori din surse diferite.

· SQLStateȘi NativeError- informații despre o eroare care a apărut dintr-o sursă de date compatibilă cu SQL.