background image

 

 

1

ADO .NET

background image

 

 

2

 

Model dostępu do danych 

za pomocą ADO.NET

Strona ASP.NET

ADO.NET

OLE DB

ODBC

SQL

Jet

itd.

background image

 

 

3

 

ADO.NET – ogólna 

architektura

ADO.NET  (ang.  ActiveX  Data  Objects)  jest  to 
technologia  umożliwiająca  dostęp  do  danych  w 
środowisku  .NET,  pozwalająca  na  korzystanie  z 
dowolnego  źródła  danych  bez  konieczności  ciągłego 
połączenia z serwerem.. 

ADO.NET pracuje w trybie bezpołączeniowym, to znaczy 
nawiązuje  połączenie  z  serwerem  i  kopiuje  dane  na 
lokalny komputer, po czym zamyka to połączenie. 

Aplikacja może, przez dowolny okres czasu, wprowadzać 
modyfikacje danych; w momencie, gdy będziemy chcieli 
zapisać zmiany, ADO.NET nawiąże ponownie połączenie 
z serwerem i zaktualizuje dane przechowywane w bazie. 

Źródłem 

danych 

może 

być 

dowolny 

magazyn 

udostępniający  dane  przez  interfejs  ODBC  lub  OLE  DB 
np.: MS SQL Server, Oracle, plik XML itp.

background image

 

 

4

Ogólny model dostępu do 

danych

background image

 

 

5

 

ADO.NET – warstwy 

dostępu do danych

W aplikacjach korzystających 

ADO.NET, 

pomiędzy 

aplikacją  a  bazą  danych  jest 

kilka 

warstw 

pośredniczących 

(dostawcy 

danych, 

sterowniki, 

interfejsy).

ADO.NET

  składa  się  z  dwóch 

podstawowych części:

– klasy 

DataSet

  i      innych 

związanych   z   nią klas, 

– z  zarządzanych 

dostawców 

danych  (Framework  Data 

Provider),

 

ułatwiających 

komunikację  ze  źródłami 

danych.

background image

 

 

6

 

ADO.NET – ogólna 

architektura cd.

background image

 

 

7

 

ADO.NET – dostawcy usług 

dostępu do danych

• Dostawca  danych

  to  zestaw  klas  pozwalających  na 

korzystanie z określonego źródła danych. Wśród nich 
znajdują się cztery podstawowe klasy:

 Connection

  -  umożliwia  nawiązanie  połączenia  z 

określonym źródłem danych.

 Command

  - wywołuje polecenie na źródle danych;  

    udostępnia kolekcję parametrów (Parameters) i 
zawsze  działa  w  kontekście  otwartego  połączenia 
(Connection) 

 DataAdapter 

 - najbliżej warstwy aplikacji; pobiera 

dane z określonego źródła i przekazuje je aplikacji 
w  określonej  formie;  wypełnia  obiekt  DataSet   
danymi  pochodzącymi  ze    źródła  oraz  umożliwia 
aktualizacje  danych  w  źródle  na  podstawie 
DataSet; 

background image

 

 

8

 

ADO.NET – dostawcy usług 

dostępu do danych

DataReader 

-  udostępnia    jednokierunkowy 

strumień    danych    ze    źródła,    w    trybie    „tylko   
do  odczytu”.  Może  zawierać  więcej  niż  jeden 
zestaw  rekordów  -  w  takim  przypadku  korzysta 
się z nich kolejno 

ADO.NET

 komunikuje  się  z bazą za  pośrednictwem 

tzw. 

Managed 

Provider

 

– 

czyli 

interfejsu 

dostępowego do konkretnej bazy danych. 

W  zależności  od  projektowanej  aplikacji,  użycie   
konkretnego  źródła  danych    może  znacząco 
wpłynąć na jej jakość.

Wybór 

dostawcy 

dostępu 

do 

danych 

jest 

uzależniony  od  rodzaju  baz  danych  jakich  używa 
dana aplikacja. 

background image

 

 

9

 

ADO.NET – dostawcy usług 

dostępu do danych

Dostawca .NET dla OLE DB

 (

.NET Framework Data 

Provider  for  OLE  DB)

  -  uzyskuje  dostęp  do  danych 

za pośrednictwem interfejsu OLE DB. 

jest  dostawcą  nadzorowanym,  gdyż  komunikuje 
się z interfejsem OLE DB za pośrednictwem klas 
opakowujących. 

może  korzystać  z  dowolnej  bazy,  dla  której 
istnieje  sterownik  OLE  DB  (Access,  Oracle,  SQL 
Server).

klasa realizująca funkcje dostawcy .NET dla OLE 
DB 

znajduje 

się 

przestrzeni 

nazw 

System.Data.OleDb.

stosowany jest dla aplikacji pracujących z wersją 
Microsoft SQL Server 6.5 i wcześniejszych

background image

 

 

10

 

ADO.NET – dostawcy usług 

dostępu do danych

Dostawca 

.NET 

dla 

SQL 

Servera 

(

.NET 

Framework 

Provider 

for 

SQL 

Server) 

 

charakteryzuje  się  znacznie  lepszą  wydajnością 
niż dostawca ogólnego przeznaczenia, jakim jest 
OLE DB. 

nie  korzysta  z  ODBC  w  czasie  połączenia  z 
bazą,  dzięki  czemu  między  kodem  aplikacji  a 
bazą jest o jedną warstwę mniej. 

klasa  realizująca  funkcje  dostawcy  .NET  dla 
SQL  Servera  znajduje  się  w  przestrzeni  nazw 
System.Data.SqlClient
.

stosowany  jest  dla  aplikacji  działających  z   
Microsoft SQL Server 7.0 i  wersjach wyższych

background image

 

 

11

 

ADO.NET – dostawcy usług 

dostępu do danych

Dostawca 

.NET 

dla 

ODBC 

(

.NET 

Framework Data Provider for ODBC) 

 - dla 

aplikacji używających ODBC.

Dostawca 

.NET 

dla 

Oracla 

(

.NET 

Framework  Data  Provider  for  Oracle) 

  - 

dla Oracle w wersji 8.1 i wyższych.

Środowisko  ADO.NET  zbudowane  jest 
wokół obiektu 

DataSet.

background image

 

 

12

Model klas DataSet

Obiekt 

DataSet

 jest prostym rezydentnym magazynem 

danych  umożliwiającym  przechowywanie  dowolnych 
informacji  (np.:  części  bazy  danych)  w  oderwaniu  od 
źródła. 

Jest  to  swego  rodzaju  lokalna  kopia  bazy  danych  lub 
jej  fragmentu.  Struktura  obiektu  DataSet  przypomina 
strukturę bazy danych. 

Dane  w  obiekcie  DataSet  przechowywane  są  w 
postaci  tabel  z  danymi,  składających  się  z  wierszy  i 
kolumn ,

Obiekt  DataSet  pozwala  na  definiowanie  związków 
pomiędzy  tabelami  oraz  nakładania  ograniczeń  na 
dane, a także umożliwia przeszukiwanie i wybieranie 
określonych rekordów 

Obiekt 

DataSet

  składa  się  z  klas: 

DataTable, 

DataRow, DataColumn, DataRelation.

background image

 

 

13

Ogólny schemat  DataSet

DataSet

ExtendedProperties

RelationsCollection

TableCollection

DataTable

ChildRelations

Columns

Constraints

DefaultView

ExtendedProperties

ParentRelations

PrimaryKeys

Rows

DataRows

DataColumns

background image

 

 

14

Model klas DataSet

Obiekt 

DataSet

 reprezentuje bufor danych w pamięci 

i  jest  podstawowym  obiektem  przekazywanym 
pomiędzy warstwą środkową a aplikacją kliencką. 

Obiekt 

DataSet 

obok  tabelarycznego  widoku  danych 

zorganizowanych  w  postaci  wierszy  i  kolumn,  może 
przekształcać dane z języka i na język XML. 

Aplikacja  wykorzystująca  obiekt  DataSet,  ma 
możliwość  sortowania,  stronicowania,  i  filtrowania 
danych, bez potrzeby ich aktualizacji. 

Klasa  DataSet  posiada  zdefiniowaną  właściwość 

Tables

,  której  wartością  jest  kolekcja  obiektów 

DataTable

 (są to tabele zawarte w obiekcie DataSet). 

background image

 

 

15

Budowa obiektu  DataSet

background image

 

 

16

Właściwości obiektu 

DataTable

Własciwość 

Opis 

CaseSensitve 

Jeżeli jej wartością jest True, to w czasie porównywania napisów 
przechowywanych w tabeli rozróżniane są małe i duże litery. 

HasErrors 

Jeżeli jej wartością jest True, to oznacza, że przynajmniej jeden element 
tabeli zawiera nieprawidłową wartość. 

PrimaryKey 

Wskazanie, która kolumna (lub kolumny)ma być kluczem głównym lub 
odczytanie klucz głównego 

TableName 

Pobranie lub ustawienie nazwy głównej tabeli. 

DefaultView  Pobranie lub ustawienie obiektu DataView, definiującego widok tabeli. 

DataSet 

Pobranie (tylko do odczytu) właściwości obiektu DataSet, do którego 
należy dana tabela. 

 

background image

 

 

17

Metody obiektu DataTable

Metoda 

Opis 

AcceptChanges 

Zatwierdza wszystkie zmiany dokonane w tabeli. 

NewRow 

Dodaje nowy wiersz do tabeli. 

RejectChanges  Odrzuca wszystkie zmiany dokonane w tabeli. 

GetChanges 

Wyniku jej działania otrzymujemy obiekt DataTable zawierający 
elementy, w których nastąpiły zmiany. 

Clone 

Tworzy kopie obiektu ( struktura, ograniczenia), która nie zawiera 
danych obiektu oryginalnego. 

Copy 

Tworzy kopie obiektu (dane, struktura). 

Clear 

Usuwa wszystkie dane z tabeli. 

ImportRow 

Dodaje wiersz reprezentowany przez obiekt DataRow. 

GetErrors 

Wynikiem jest tablica obiektów DataRow zawierających błędy. 

Select 

Wynikiem działania jest tabela zawierająca elementy spełniające warunki 
określone przez argumenty. 

 

background image

 

 

18

Zdarzenia obiektu 

DataTable

Dla obiektu 

DataTable

 możliwe jest 

wystąpienie następujących zdarzeń:

RowChanged 

– zgłaszane, gdy wiersz 

został zmieniony.

ColumnChanged 

– zgłaszane, gdy 

zmieniono wartość w kolumnie.

RowDeleted

 – zgłaszane, gdy wiersz został 

usunięty.

background image

 

 

19

Kolekcja DataRow

Klasa 

DataTable

 

posiada 

zdefiniowaną 

właściwość 

Row

,  której  wartością  jest  kolekcja 

obiektów 

DataRow

  (są  to  wiersze  zawarte  w 

obiekcie DataTable). 

Obiekt 

DataRow

  reprezentuje  jeden  wiersz 

tabeli, przez co umożliwia dodawanie, usuwanie 
i  modyfikację  danych,  przechowywanych  w 
tabeli,  w  ograniczeniu  tylko  do  jednego 
elementu. 

background image

 

 

20

Właściwości obiektu 

DataRow

background image

 

 

21

Metody obiektu DataRow

Metoda

Opis

AcceptChanges

Zatwierdza wszystkie zmiany wprowadzone w wierszu.

ClearErrors

Usuwa błędy ustawione dla danego wiersza.

Delete

Usuwa wiersz tabeli

ToString

Przedstawia obiekt w postaci napisu

RejectChanges

Odrzuca wszystkie zmiany, które wystąpiły w danym
wierszu.

GetType

Tworzy obiekt z informacjami o typie obiektu

GetColumnError Wynikiem działania jest komunikat o błędzie kolumny

skojarzonej z danym argumentem.

background image

 

 

22

Kolekcja DataColumn

DataTable

 

posiada 

zdefiniowaną 

właściwość 

Columns

,  której  wartością  jest 

kolekcja  obiektów 

DataColumn

  (są  to 

kolumny zawarte w obiekcie DataTable). 

Obiekt 

DataColumn

 reprezentuje strukturę 

obiektu DataTable (każda kolumna określa 
określony typ danych, jakie mogą się w niej 
znajdować (format i ograniczenia tabeli).

background image

 

 

23

Właściwości obiektu 

DataColumn

Właściwości 

Opis 

AllowDBNull 

Określa czy w kolumnie może wystąpić wartość pusta, Null. 

AutoIncrement  Określa czy wartość w kolumnie, podczas dodawania nowych wierszy 

jest automatycznie zwiększana.  

Caption 

Pobranie lub ustawienie wyświetlanej nazwy kolumny. 

ColumnName  Pobranie lub ustawienie nazwy kolumny. 

DataType 

Pobranie lub ustawienie, jakiego typu dane mogą znaleźć się w kolumnie. 

DefaultValue  Pobranie lub ustawienie wartości domyślnej, jaka znajduje się w 

kolumnie podczas dodawania nowych wierszy. 

MaxLength 

Pobranie lub ustawienie maksymalnej długości napisu w kolumnie, 
(jeżeli kolumna zawiera napisy) 

ReadOnly 

Pobranie lub ustawienie wartości określającej czy wartości w danej 
kolumnie są tylko do odczytu. 

Table 

Pobranie (tylko do odczytu) właściwości obiektu DataTable, do którego 
należy dana kolumna. 

Unique 

Pobranie lub ustawienie wartości wskazującej czy dane zawarte w danej 
kolumnie maja charakter unikalny (nie mogą się powtarzać). 

 

background image

 

 

24

Metody obiektu 

DataColumn

background image

 

 

25

Wielowersyjność w 

obiekcie DataSet

Obiekt 

DataSet

 przechowuje dwie wersje wszystkich 

danych,  a  w  czasie  edycji  wiersza,  po  wykonaniu 
metody 

DataRow.BeginEdit

  tworzona  jest  trzecia 

kopia, zawierająca wszystkie zmiany:

zmiany zatwierdzane są metodą 

DataRow.EndEdit

 

zmiany 

odrzucane 

są 

metodą 

DataRow.CancelEdit

Dane,  którymi  napełniono  obiekt  DataSet  stanowią 

wersję  oryginalną

  i  służą  do  stworzenia 

wersji 

bieżącej

, na której wykonywane są modyfikacje. 

Przy  wykonaniu  metody 

DataSet.AcceptChanges

 

dane  z  wersji  bieżącej  przenoszone  są  do  wersji 
oryginalnej,  lub  zmiany  zostają  odrzucone    przez 
wykonanie metody 

DataSet.RejectChanges

background image

 

 

26

Relacje w obiekcie DataSet

background image

 

 

27

Relacje w obiekcie DataSet

Związki pomiędzy tabelami w obiekcie DataSet 
reprezentowane  są  przez  kolekcję  obiektów 

Relations

.

Przykładowo,  definiowanie  związku  pomiędzy 
tabelami: 

tabela1

 i 

tabela2 

w obiekcie DataSet 

o nazwie 

ds 

w języku C# ma postać:

ds.Relations.Add("Relacja",

ds.Relations.Add("Relacja",

ds.Tables("tabela1").Columns("AdresID"),

ds.Tables("tabela1").Columns("AdresID"),

d

d

s.Tables("tabela2").Columns("AdresID");

s.Tables("tabela2").Columns("AdresID");

Najczęstszą metodą tworzenia obiektu DataSet 
jest wczytanie jego struktury z pliku   

XML

background image

 

 

28

Tworzenie obiektu 

DataSet w kodzie 

programu

W takim wypadku, należy tworzyć obiekt DataSet w 
kodzie  programu,  co  umożliwia  zdefiniowanie  jego 
struktury  oraz  typu  danych,  jakich  będą  używać 
poszczególne kolumny. 

Przykładowy  kod  w  języku  C#,  tworzący  obiekt 
DataSet (

ds

) o nazwie „Baza”, który będzie zawierał 

jedną  tabelę  (

dt

)  o  nazwie  „dane”.  Tabela  zawiera 

dwa wiersze (

dr

) zawierające zdefiniowane dane.

 

System.Data.DataSet ds = new DataSet("Baza");

System.Data.DataTable 

dt 

new 

DataTable("dane");

System.Data.DataRow dr;

background image

 

 

29

Tworzenie obiektu 

DataSet w kodzie 

programu

//Zdefiniowanie 

struktury 

tabeli(Columns) 

typów 

wykorzystywanych elementów

dt.Columns.Add("ID", Type.GetType("System.Int32"));
dt.Columns.Add("Imie" ,Type.GetType("System.String"));
dt.Columns.Add("Nazwisko" 

,Type.GetType("System.String"));

dt.Columns.Add("Adres", Type.GetType("System.String"));

//Utworzenie  pierwszego  wiersza  i  przypisanie  wartości 

poszczególnym elementom

dr=dt.NewRow();
dr["ID"]=1;
dr["Imie"] = "Szczepan";

background image

 

 

30

Tworzenie obiektu 

DataSet w kodzie 

programu

 

dr["Nazwisko"]="Wozniak";

dr["Adres"] = "Kaszew";
dt.Rows.Add(dr);//dodanie wiersza do tabeli dt

//Utworzenie  drugiego  wiersza  i  przypisanie  wartości 

poszczególnym elementom

dr = dt.NewRow();
dr["ID"]= 2;
dr["Imie"] = "Rafał";
dr["Nazwisko"]="Leśniak";
dr["Adres"] = "Turek";
dt.Rows.Add(dr); 

//dodanie wiersza do tabeli dt

ds.Tables.Add(dt);   

//Zapisanie  tabeli  w  obiekcie 

DataSet

background image

 

 

31

Właściwości klasy DataSet

CaseSensitive

Właściwość określa czy przy porównywaniu

łańcuchów znaków w tym obiekcie 

DataSet

będzie uwzględniana wielkość liter.

DataSetName

nazwa danego obiektu 

DataSet

.

DefaultViewManager

Zwraca obiekt klasy 

DataViewManager

zawierający informacje o zmodyfikowanym

sposobie prezentacji danego obiektu 

DataSet

.

EnforceConstraints

Właściwość określa czy przy aktualizacji

danych mają być wymuszane reguły.

ExtendedProperties

Obiekt 

PropertyCollection

 zawierający

informacje określane przez użytkownika.

background image

 

 

32

Właściwości klasy DataSet

background image

 

 

33

Właściwości klasy DataSet

background image

 

 

34

Właściwości klasy DataSet

background image

 

 

35

                 EndInit

Zakańcza proces inicjalizacji obiektu

DataSet

 w trakcie działania programu.

         GetChanges

Tworzy nowy obiekt klasy 

DataSet

zawierający wyłącznie dane, które zostały

zmodyfikowane.

         HasChanges

Określa czy informacje w danym obiekcie

DataSet

 uległy jakimkolwiek zmianom.

  InferXmlSchema

Tworzy strukturę danych na podstawie

źródła danych XML. Metoda przeciążona,

więcej informacji na jej temat można

znaleźć w dokumentacji .NET SDK.

    Marge(DataSet)

Łączy dany obiekt 

DataSet

 z obiektem

podanym jako argument wywołania

metody.

Właściwości klasy DataSet

background image

 

 

36

Właściwości klasy DataSet

background image

 

 

37

Właściwości klasy DataSet

background image

 

 

38

MergeFailed

Zdarzenie jest generowane gdy zarówno źródłowy

jak i docelowy obiekt 

DataSet

 będzie miał tę samą

wartość klucza głównego, a jednocześnie

właściwość 

EnforceConstraints

 będzie miała

wartość 

true

.

PropertyChanged

Zdarzenie jest generowane w razie modyfikacji

którejś z właściwości kolumny. Argumentem

wywołania procedury obsługi tego zdarzenia jest

obiekt klasy 

PropertyChangedEventArgs

,

zawierający następującą właściwość:

PropertyName

 — Nazwa właściwości która uległa

zmianie.

Zdarzenia klasy DataSet

background image

 

 

39

Połączenie ze źródłem 

danych

W ADO.NET połączenie ze źródłem danych realizowane jest 
to  za  pomocą  klas: 

DataAdapter,  Connection,  Command    i 

DataReader

, zdefiniowanych dla OLEDB oraz SQL Servera

background image

 

 

40

Połączenie ze źródłem 

danych

Połączenie  między  obiektem 

DataSet

  a  źródłem 

danych umożliwia obiekt 

DataAdapter.

 

W przypadku, gdy źródłem danych jest dokument 
XML  lub,  gdy  obiekt  DataSet  budujemy  w  kodzie 
programu obiekt DataAdapter nie jest potrzebny. 

Obiekt DataAdapter posiada dwie główne 

metody

są to:

Fill 

–  nawiązuje  połączenie  z  bazą  danych, 

wysyła  żądanie  odczytu  ze  źródła    i  umieszcza 
otrzymane dane w obiekcie DataSet. 

Update 

–  sprawdza,  jakie  zmiany  nastąpiły  w 

obiekcie  DataSet  i  przesyła  elementy,  które 
zostały zmodyfikowane do źródła danych. 

background image

 

 

41

Połączenie ze źródłem 

danych

Metody  zawarte  w   

DataAdapter

  dostępne  są 

dla dostawcy:

OLEDB w klasie 

System.Data.OleDb.OleDbDataAdapter 

SQL Server w klasie 

System.Data.SqlClient.SqlDataAdapter

 

background image

 

 

42

Model obiektu 

DataAdapter

 

DataAdapter 

DeleteCommand 

I nsertCommand 

SelectCommand 

UpdateCommand 

TableMappings 

ColumnMappings 

Metody 

Command,

  obiektu 

DataAdapter

  służą 

do modyfikacji danych w obiekcie 

DataSet

Kolekcja 

TableMappings

 

określa 

sposób 

odwzorowania  w  obiektach 

DataSet 

tabel  i 

kolumn ze źródła danych. 

background image

 

 

43

Metody obiektu 

DataAdapter

Metoda

Opis

Fill

Dodaje  lub  modyfikuje  wiersze  w 
obiekcie DataSet

FillSchema

Dodaje  obiekt  DataTable  do  obiektu 
DataSet i konfiguruje schemat tabeli

GetFillParamet
ers

Zwraca 

tablicę 

obiektów 

IDataParameter 

używanych 

poleceniu Select

Update

Aktualizuje  zawartość  źródła  danych 
na  podstawie  informacji  zapisanych 
w obiekcie Dataset, wykorzystując do 
tego  właściwości  DeleteCommand, 
InsertCommand, Update Command

background image

 

 

44

Zdarzenie

Opis

FillError

Zdarzenie 

zachodzi 

gdy 

podczas 

wykonywania 

metody 

Fill 

zostanie 

zgłoszony błąd. Argumentem jest obiekt 
FillErrorEventArgs.

RowUpdated

Zachodzi 

trakcie 

wykonywania 

metody Update, po wykonaniu polecenia 
UPDATE. 

Argument 

obsługi 

jest 

obiektem  klasy  RowUpdatedEventArgs, 
która  udostępnia właściwości:
Command – zwraca obiekt Command 
Errors  –  zwraca  obiekt  Exception 
RecordsAffected 

– 

podaje 

ilość 

zmodyfikowanych wierszy 
StatementType  –  zwraca  typ  polecenia 
SQL
Row – zwraca obiekt DataRow 
TableMapping  –  zwraca  obiekt  klasy 
DatatableMapping 

przesłany 

poleceniem SQL

RowUpdating

Zdarzenie 

zachodzi 

podczas 

wykonywania  metody  Update,  przed 
wykonaniem  polecenia  SQL  UPDATE. 
Argument  obsługi  jest  obiektem  klasy 
RowUpdatedEventArgs. 

Klasa 

ta 

udostępnia  takie  same  właściwości  jak 
zdarzenie RowUpdated

background image

 

 

45

            string sCnStr = ”northwind";
            string sSQL = "select * from customers";
            SqlConnection Cn = new 
SqlConnection(sCnStr);
            SqlDataAdapter DA = new 
SqlDataAdapter(sSQL,Cn);

// utworzenie uchwytów dla zdarzeń

DA.RowUpdating += new 

    

SqlRowUpdatingEventHandler(onRowUpdatin
g);
DA.RowUpdated += new  
SqlRowUpdatedEventHandler(onRowUpdated
);

DA.FillError += new 
FillErrorEventHandler(FillErrorHandler);

            DataSet Ds = new DataSet();

Zdarzenia obiektu 

DataAdapter  - przykład

background image

 

 

46

//wypełnienie DataSet danymi 

            DA.Fill(Ds,”customers");
 

//tworzenie nowego wiersza do aktualizacji

            DataRow DR = 
Ds.Tables[”customers"].Rows[2];

//uaktualnienie wymaganego wiersza

            DR["PASSWORD"] = "NET";

//tworzenie obiektu do dynamicznego  aktualizowania

SqlCommandBuilder Cb = new 
SqlCommandBuilder(DA);

DA.Update(Ds,”customers"); 

Zdarzenia obiektu 

DataAdapter  - przykład

background image

 

 

47

Zdarzenia obiektu 

DataAdapter i ich 

wykorzystanie cd.

// usunięcie uchwytów do zdarzeń

DA.RowUpdating - = new  
SqlRowUpdatingEventHandler(onRowUpdating
);
DA.RowUpdated  -  = new  
SqlRowUpdatedEventHandler(onRowUpdated);
DA.FillError - = new 
FillErrorEventHandler(FillErrorHandler);

DA.Dispose();
Cn.Close();

 

background image

 

 

48

Połączenie z bazą danych

Do  połączenia  z  bazą  danych  służy  obiekt 

Connection

, którego zadaniem jest:

nawiązanie połączenia  metodą 

Open( ),

 

kontrolowanie połączenia

zamknięcie  połączenia  pomiędzy  aplikacją  i 
bazą danych metodą 

Close( ).

 

Obiekt  Connection  jest  wykorzystywany  przez 
obiekty 

DataAdapter 

Command

  w  czasie 

realizacji połączenia.

Metody  obsługujące  obiekt  Connection  dostępne 
są dla dostawcy:

OLEDB w klasie 

System.Data.OleDb.OleDbConnection

 

SQL Server w klasie

 

System.Data.SqlClient.SqlConnection

background image

 

 

49

Połączenie z bazą danych 

SQL

• Podłączenie do SQL Server za pomocą .

NET Framework 

Provider  for  SQL  Server

  jest  realizowane  przez  obiekt 

SqlConnection 

tworzący  połączenie,  które  zostaje 

potem otwarte przy pomocy metody 

Open()

SqlConnection 

con 

new 

SqlConnection("server=localhost;

     database=Northwind;uid=sa;pwd=;");
  con.Open();

• Przy tworzeniu wielu połączeń w jednej aplikacji, należy 

tworzyć 

pule  połączeń, 

ponieważ  pozwalają  one 

zmniejszyć czas dostępu do danych jak i ruch pomiędzy 
bazą  danych  a  programem  z  niej  korzystającym. 
Wpływają  także  w  znacznym  stopniu  na  poprawę 
wydajności, skalowalności i niezawodności aplikacji.

background image

 

 

50

Połączenie z bazą danych 

SQL

• 

ADO.NET

  pule  połączeń  są  identyfikowane  za 

pomocą  przypisanych  im  danych  konfiguracyjnych 
(ciąg 

znaków 

właściwości 

ConnectionString

 

dziedziczonej  po  interfejsie 

IDbConnection

  przez 

wszystkie  klasy  odpowiedzialne  za  łączenie  z 
bazami danych). 

• Podczas  wywoływania  metody 

Open()

  klasy 

SqlConnection

  specjalny  system  sprawdza  na 

podstawie  wartości  właściwości 

ConnectionString

 

czy istnieje już pula o podanym identyfikatorze. 

• Jeżeli nie ma jeszcze odpowiedniej puli to jest ona 

tworzona  wraz  z  minimalną  wymaganą  ilością 
połączeń  i  jedno  z  nich  jest  oddawane  do  użytku 
obiektu, który zgłaszał żądanie.

background image

 

 

51

Połączenie z bazą danych 

SQL

• Gdy  wszystkie połączenia są  już  zajęte, tworzone są 

nowe,  aż  do  górnego  limitu  ustalonego  dla  danej 
puli. 

• Osiągnięcie 

maksymalnej, 

dozwolonej 

ilości 

wykorzystywanych 

połączeń 

puli 

skutkuje 

ustawieniem  żądania  w  kolejce  do  czasu  zwolnienia 
jakiegoś z istniejących połączeń.

• Zwolnienie  połączenia  i  zwrócenie  go  do  puli 

odbywa  się  po  wywołaniu  metody 

Close()

  lub 

Dispose()

  klasy 

SqlConnection

.  Jest  ono  wtedy 

oznaczane jako nieużywane i czeka w puli na kolejne 
użycie.

background image

 

 

52

Połączenie z bazą danych 

SQL

SqlConnection connection1 = new SqlConnection(); 

SqlConnection connection1 = new SqlConnection(); 

connection1.ConnectionString="userid=sa;datasource=

connection1.ConnectionString="userid=sa;datasource=

\"WINDOWSXP\\SQLDB\";persist "+ "security 

\"WINDOWSXP\\SQLDB\";persist "+ "security 

info=False;initial catalog=northwind";

info=False;initial catalog=northwind";

connection1.Open();

connection1.Open();

// Utworzenie pierwszej puli (A).

SqlConnection connection2 = new SqlConnection();

SqlConnection connection2 = new SqlConnection();

connection2.ConnectionString="userid=sa;datasource=

connection2.ConnectionString="userid=sa;datasource=

\"WINDOWSXP\\SQLDB\";persist "+ "security 

\"WINDOWSXP\\SQLDB\";persist "+ "security 

info=False;initial catalog=pub";

info=False;initial catalog=pub";

connection2.Open();

connection2.Open();

// Utworzenie drugiej puli (B)

background image

 

 

53

Połączenie z innymi 

źródłami danych

• W

 .NET Framework Data Provider for OLE DB

 

połączenie uzyskuje się poprzez obiekt 

OleDbConnection,

 

OleDbConnection Con = new 

OleDbConnection Con = new 

OleDbConnection("Provider=SQLOLEDB;Data 

OleDbConnection("Provider=SQLOLEDB;Data 

Source=localhost;" + "Integrated Security=SSPI;Initial 

Source=localhost;" + "Integrated Security=SSPI;Initial 

Catalog=northwind"); nwindConn.Open();

Catalog=northwind"); nwindConn.Open();

• .NET Framework Data Provider for ODBC

 do tworzenia 

połaczeń korzysta z 

OdbcConnection

OdbcConnection Con = new 

OdbcConnection Con = new 

OdbcConnection("Driver={SQL 

OdbcConnection("Driver={SQL 

Server};Server=localhost;" + 

Server};Server=localhost;" + 

"Trusted_Connection=yes;Database=northwind"); 

"Trusted_Connection=yes;Database=northwind"); 

Con.Open();

Con.Open();

background image

 

 

54

Połączenie z innymi 

źródłami danych

• .NET  Framework  Data  Provider  for  Oracle 

tworzy 

połączenie 

przy 

pomocy 

OracleConnection

 

OracleConnection 

OracleConnection 

Con=newOracleConnection("Data 

Con=newOracleConnection("Data 

source=MyOracleServer;

source=MyOracleServer;

Integrated Security=yes;"); 

Integrated Security=yes;"); 

nwindConn.Open();

nwindConn.Open();

background image

 

 

55

Właściwości obiektu 

Connection

Właściwość

Opis

ConnectionStrin
g

Łańcuch  znaków  służący  do  utworzenia 
połączenia

ConnectionTime
out

Czas  jaki należy  oczekiwać  na  połączenie 
z bazą danych

Database

Nazwa  bazy  danych,  z  którą  należy 
korzystać po nawiązaniu połączenia

DataSource

Nazwa  bazy  danych  z  jaką,  należy 
nawiązać połączenie

Provider

Nazwa dostawcy bazy danych

State

Bieżący stan połączenia

background image

 

 

56

Metody obiektu 

Connection

Metoda

Opis

BeginTransact
ion

Rozpoczyna  transakcję  z  bazy 
danych

Close

Zamyka połączenie z bazą danych

Open

Otwiera połączenie z bazą danych

background image

 

 

57

Wykonywanie instrukcji 

SQL

Obiekt 

Command

 umożliwia wykonanie instrukcji 

SQL  w  celu  uzyskania  kolekcji  obiektów 
spełniających określone kryteria. 

Obiekt  Command  umożliwia  również    wykonanie 
instrukcji 

INSERTDELETEUPDATE i SELECT

W  celu  wykonania  instrukcji  języka  SQL  należy 
właściwości 

CommandText

  obiektu 

Command 

przypisać treść instrukcji.

Metody  obsługujące  obiekt  Command  dostępne 
są dla dostawcy:

OLEDB w klasie 

System.Data.OleDb.OleDbCmmand

 

SQL Server w klasie 

System.Data.SqlClient.SqlCmmand

background image

 

 

58

Model obiektu Command

 

 

Command 

Connection 

Parameters 

Properties 

Properties 

Parameter 

Property 

background image

 

 

59

Wykonywanie instrukcji 

SQL

Przykładowo, 

wykorzystanie 

obiektu 

Command

  dla  wykonania  instrukcji  SELECT 

w języku C#  ma postać: 

 

SqlCommand c = new SqlCommand();

// definiowanie obiektu Command 

c.CommandText  =  "SELECT*FROM  Baza 

WHERE ID>3” 

//  definiowanie  kwerendy  wybierającej  z  tabeli 

Baza  

// elementów, których ID>3

background image

 

 

60

Wykonywanie instrukcji 

SQL

• Jednym  ze  sposobów  komunikacji  z  serwerem  baz 

danych  jaki  udostępnia 

ADO.NET

  jest  komunikacja 

pasywna. 

• Do 

realizacji 

pasywnej 

wymiany 

danych 

wykorzystywany  jest  obiekt 

SqlCommand

,  który 

określa parametry komendy przekazywanej serwerowi. 

• Obiekt  ten  może  zadaną  komendę  wykonać,  zwracając 

zbiór  rekordów  z  bazy  danych,  wartość  skalarną  lub 
pusty zbiór wyników, w zależności od postaci komendy. 

• Zbiór rekordów będących wynikiem działania komendy 

SQL zostanie zwrócony dzięki metodzie 

ExecuteReader

 

obiektu 

SqlCommand

;  dokładniej  mówiąc,  wynikiem 

działania 

tej 

metody 

będzie 

obiekt 

typu 

SqlDataReader

który 

pozwala 

na 

obejrzenie 

wszystkich wierszy wyniku. 

background image

 

 

61

Właściwości obiektu 

Command

Właściwość

Opis

CommandText

Polecenie SQL

CommandType

Określa 

sposób 

interpretacji 

polecenia SQL

Connection

Określa obiekt Connection

Parameters

Zwraca 

obiekt 

ParameterCollection, 
reprezentujący 

wszystkie 

parametry w poleceniu SQL

Transaction

Obiekt  Transaction  używany  przez 
Command

UpdateRowSo
urce

Liczba 

wierszy 

objętych 

poleceniem  SQL;  w  przypadku 
poprawnego  polecenia  wartość  ta 
wynosi 1

background image

 

 

62

Metody obiektu Command

Metoda

Opis

Cancel

Przerywa wykonanie polecenia

CreateParam
eter

Tworzy obiekt Parameter

ExecuteNonQ
uery

Wykonuje  polecenie  SQL,  które 
nie zwraca żadnych danych

ExecuteReade
r

Zwraca 

obiekt 

DataReader 

zawierający  dane  uzyskane  w 
wyniku wykonania polecenia SQL

background image

 

 

63

Dostęp do danych

Dostęp do danych zapisanych w magazynie danych 
umożliwia  obiekt 

DataReader 

,  który  wyświetla  je 

w postaci strumienia

Jest  to  bardzo  szybka  metoda  dostępu  do  danych 
uniemożliwiająca jednak ich modyfikację. 

Obiekt 

DataReader

:

w  celu  nawiązania  połączenia  z  bazą  danych 
korzysta z obiektu 

Connection 

w  celu  określenia,  jakie  dane  mają  być 
odczytane, korzysta z obiektu 

Command.

 

Obiekt  DataReader  nie  korzysta  a  obiektu 
DataSet

,  dane  wysyłane  są  bezpośrednio  do 

kontrolek umieszczonych w aplikacji.

background image

 

 

64

Dostęp do danych 

SqlDataReader 

myReader 

myCommand. 

SqlDataReader 

myReader 

myCommand. 

ExecuteReader();

ExecuteReader();

• DataReader

  umieszcza  w  pamięci  jednorazowo  tylko 

jeden  wiersz  danych;  na  żądanie  tworzy  strumień 
danych z magazynu danych. Zapobiega to występowaniu 
wielu  problemów  związanych  z  dostępna  pamięcią,  co 
daje w wyniku poprawę wydajności systemu. 

• Obiekt  ten  jest  tylko  do  odczytu,  nie  można  również   

powracać do rekordów, które zostały już przetworzone.

• Po zapisaniu danych w obiekcie, aby przejść do 

kolejnych rekordów należy  wywołać metodę 

Read()

 .

Metoda 

Read

 obiektu 

DataReader

 powoduje przejście do 

następnego poprawnego rekordu (o ile taki istnieje).

background image

 

 

65

Dostęp do danych 

Jedno 

wykonanie 

metody 

Read 

obiektu 

DataReader

, zwraca jeden rekord danych. 

while(reader.Read())

while(reader.Read())

{

{

myString = reader.Item(0).ToString();

myString = reader.Item(0).ToString();

myInt = reader.GetInt32(1); 

myInt = reader.GetInt32(1); 

}

}

Metoda 

Read

 

powoduje 

przesunięcie 

wewnętrznego  wskaźnika  danych  do  następnego 
rekordu,  nie  powodując  rzeczywistego  odczytu 
danych. 

Faktyczny odczyt ma miejsce dopiero po wykonaniu 
metody 

GetString

 lub 

GetValues

background image

 

 

66

Dostęp do danych 

Klasa 

DataReader

 musi więc posiadać, co najmniej 

dwa konstruktory, 

jeden pobierający zestaw wynikowy kwerendy 

drugi, 

który 

dokonuje 

pobrania 

obiektu 

połączenia  wykorzystywanego  do  wykonania 

polecenia.

Metody  obsługujące  obiekt 

DataReader

  dostępne 

są dla dostawcy:

OLEDB w klasie 

System.Data.OleDb.OleDbDataReader

 

SQL Server w klasie
 

System.Data.SqlClient.SqldataReader

background image

 

 

67

Właściwości obiektu 

DataReader

Właściwość

Opis

FieldCount

Ilość  pól  dostępnych  w  danym 
rekordzie

IsClosed

Określa 

czy 

obiekt 

został 

zamknięty

Item

Zwraca 

wartość 

wybranej 

kolumny

RecordsAffec
ted

Okresla  ilość  wierszy  objętych 
wynikami  działania  polecenia 
SQL;  w  przypadku  poprawnego 
wykonania 

zwraca 

1, 

przypadku błędu  zwraca -1

background image

 

 

68

Metoda

Opis

Close

Zamyka obiekt DataReader

GetFieldType 
(indeks)

Zwraca  obiekt  reprezentujący  typ 
danych wskazanego obiektu

GetName 
(indeks)

Zwraca nazwę kolumny

GetValue 
(indeks) 

Zwraca  wartość  kolumny  w  jej 
oryginalnym formacie

GetString 
(indeks)

Zwraca  wartość  kolumny  jako 
String

IsDBNull

Metoda 

stosowana 

do 

przedstawiania 

nieistniejących 

wartości

NextResult

przypadku 

wykorzystania 

wyników 

wsadowego 

polecenia 

SQL, metoda ta przesuwa obiekt do 
następnego rekordu

Read

Przesuwa  obiekt  do  następnego 
rekordu

background image

 

 

69

Dostęp do danych - 

przykład 

Wykorzystanie  obiektów 

Connection,  Command

 

oraz 

DataReader

 w celu wyświetlenia informacji o 

błędnych 

wierszach 

zawartych 

obiekcie 

DataAdapter

  (

da

),  ujawnionych  w  trakcie  próby 

aktualizacji źródła danych (

Update

). 

klasa 

Connection

  realizuje  połączenie  ze 

źródłem danych. 

klasa 

DataReader

, odczytuje elementy określone 

przez  klasę 

Command

  (za  pomocą  kwerendy 

wybiera  elementy,  w  których  wystąpił  błąd),  i 
zapisuje  je  do  tablicy,  która  następnie  zostanie 
wyświetlona  w postaci kontrolki informacyjnej.

background image

 

 

70

Dostęp do danych - 

przykład 

 

try  {

da.Update(ds,"Baza"); 

//aktualizacja 

źródła 

obiektu 

DataAdapter   

}

catch (DBConcurrencyException dbcex) 

// w przypadku błędu aktualizacji zwracany jest wyjątek

{
SqlCommand  c =  new SqlCommand(); 

//  definiowanie 

obiektu

Command c.CommandText = "SELECT*FROM Baza 
WHERE ID="+dbcex.Row["ID"].ToString();

//konfiguracja  wyszukiwana  konkretnego  elementu  w  bazie 

danych

background image

 

 

71

Dostęp do danych - 

przykład 

c.Connection  =  polaczenie;

            //  definiowanie  obiektu 

Connection

polaczenie.Open();

            // otwarcie połączenia z bazą danych

SqlDataReader dr = new SqlDataReader();

// zdefiniowanie obiektu DataReader 

dr.Read();

     // odczytanie rekordu określonego przez kwerendę 

Object  []  rg  =  new  Object[NR_Wiersza];

            //  utworzenie 

tablicy

dr.GetValues(rg);

         // zapisanie rekordu w tablicy

dr.Close();

                   // zamknięcie czytnika danych

polaczenie.Close();

       // zamknięcie połączenia

conflict.Display(dbcex.Row, rg);

 

}

// wyświetlenie danych w kontrolce użytkownika

background image

 

 

72

Wykonywanie operacji SQL 

nie zwracających danych 

(INSERT,UPDATE,DELETE)

• Ponieważ  obiekt 

DataReader

  jest    tylko  do 

odczytu,  więc  nie  umożliwia  modyfikowania 
danych. 

• Do  modyfikacji  danych  należy  użyć  instrukcji 

języka 

SQL 

(Update,Insert,Delete 

jako 

parametru obiektu 

Command

.

• W  celu  określenia  liczby  rekordów,  które  zostały 

zmienione należy użyć metody 

ExecuteNonQuery

.

int wyswietl = MyCommand.ExecuteNonQuery();

background image

 

 

73

SqlConnection con = new 
SqlConnection("server=localhost; 

database=Northwind;uid=sa;pwd=;");

SqlCommand cmd = new SqlCommand();
cmd.CommandText = "DELETE FROM 
Customers WHERE 
CustomerName =’ZED'";

cmd.Connection = con;
con.Open();

Console.WriteLine(cmd.ExecuteNonQuery().To
String());

con.Close()

Program zwraca numery wierszy dla których 
zostało wykonane polecenie DELETE. 

Wykonywanie operacji 

SQL nie zwracających 

danych 

(INSERT,UPDATE,DELETE) 

cd.

background image

 

 

74

Model przechwytywania 

wyjątków – klasa SQL 

Exception

Obiekty  klasy 

SqlException

  -  opisują  błędy 

zgłaszane przez bazę danych od strony serwera. 

Błędy mają następujące poziomy istotności:

1-10  to  błędy  informacyjne  które  wskazują  na 
pomyłki w danych otrzymanych od użytkownika,

11-16  błędy  generowane  przez  użytkownika   
które on może poprawić,

17-25  wskazują  na  błędy  oprogramowania  lub 
sprzętu; 

błędy 

17-19 

umożliwiają 

kontynuowanie  pracy  natomiast  przy    20  i 
powyżej  połączenie   

SqlConnection

  zostaje 

zamknięte. 

background image

 

 

75

Try

{
sqlConnection.Open();
sqlInsertCommand.ExecuteNonQuery();
sqlConnection.Close();
MessageBox.Show(”Operacja zakończona 

sukcesem",”OK",MessageBoxButtons.OK);

}

catch (SqlException blad)

{

foreach(SqlError err in blad.Errors)

{   MessageBox.Show(”Błąd: " + err.Number + 
" : " +  

   err.Message);

}

}

finally

{

sqlConnection.Close();

}

Model przechwytywania 

wyjątków – klasa SQL 

Exception

background image

 

 

76

Użycie procedur 

składowanych,

• Procedury  składowane    umożliwiają  zawarcie  w 

jednym rozkazie  wielu operacji na bazie danych. 

• Przykładowa procedura 

bez parametrów

 ma postać:

SqlConnection con = new 

SqlConnection con = new 

SqlConnection("server=localhost; 

SqlConnection("server=localhost; 

                              

                              

        database=Northwind;uid=sa;pwd=;");

        database=Northwind;uid=sa;pwd=;");

SqlCommand cmd = new 

SqlCommand cmd = new 

SqlCommand(”Najdrozsze_produkty", con);

SqlCommand(”Najdrozsze_produkty", con);

cmd.CommandType = 

cmd.CommandType = 

CommandType.

CommandType.

StoredProcedure

StoredProcedure

;

;

con.Open();

con.Open();

SqlDataReader reader = cmd.ExecuteReader();

SqlDataReader reader = cmd.ExecuteReader();

while(reader.Read())

while(reader.Read())

{

{

Console.WriteLine("{0} - {1:C}", 

Console.WriteLine("{0} - {1:C}", 

reader.GetString(0),reader.GetDecimal(1));

reader.GetString(0),reader.GetDecimal(1));

}

}

con.Close();

con.Close();

background image

 

 

77

Użycie procedur 

składowanych,

• Przykładowa procedura 

z parametrami

 ma postać:

SqlConnection con = new 
SqlConnection("server=localhost; 
database=Northwind;uid=sa;pwd=;");
SqlCommand cmd = new SqlCommand 
(”

Najdrozsze_produkty

Najdrozsze_produkty 1", con);

cmd.CommandType = 
CommandType.StoredProcedure;

cmd.Parameters.Add(new SqlParameter("@country", 
SqlDbType.VarChar, 50)).Value = "USA";
cmd.Parameters.Add(new SqlParameter("@count", 
SqlDbType.Int));
cmd.Parameters["@count"].Direction = 
ParameterDirection.

Output

;

con.Open();

con.Open();

SqlDataReader reader = cmd.ExecuteReader();

SqlDataReader reader = cmd.ExecuteReader();

background image

 

 

78

Użycie procedur 

składowanych,

Przykładowa  procedura 

z  parametrami

  ma  postać 

(cd) :

while(reader.Read())
{
Console.WriteLine("{0} - {1}", 
reader.GetString(0),reader.GetString(1));
}

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

con.Close();

background image

 

 

79

Procedury parametryczne

 parametry wejściowe i 

wyjściowe

• Procedura  zwraca  jako  parametr  wyjściowy 

wszystkie  rekordy  z  tabeli 

Customers 

w  których 

pole 

Country

 jest podane parametrem 

@country

.

• Obiekt 

Command

  umożliwia  jawne  definiowanie 

parametrów (

Parameter

) procedury a także dostęp 

do parametrów wyjściowych i zwracanych wartości.

• Domyślnie    parametry  są  traktowane  jako 

wejściowe (

Input

).

• Aby  wyszczególnić  typ  parametru  używa  się 

właściwości 

ParameterDirection

,  przy  pomocy 

której  można  określić    czy  parametry  są 

InputOutput

 

(wejściowe  i  wyjściowe), 

Output

 

(wyjściowe), albo

 

ReturnValue

 

(zwracana wartość).

background image

 

 

80

Pobieranie skalarów z baz 

danych

• Do zwrotu pojedynczej wartości z bazy takiej 

jak  np.:  wynik  operacji 

Count  (*)

  ,  służy 

metoda  

ExecuteScalar

 

obiektu

 Command. 

• Zwraca  ona

 

wartość  skalarną

 

pierwszej 

kolumny  z  pierwszego  wiersza  danych  ze 
zbioru wyników.

MyCommand.CommandText = "SELCT 
COUNT(*) FROM 

Customers";

int nr_c = (int)myCommand.ExecuteScalar();

background image

 

 

81

Transakcje w ADO.NET

Do  operowania  transakcjami  w  ADO.Net  służy  klasa 

System.Data.SqlClient.SqlTransaction

.  Jest  to  pewne 

novum  w  stosunku  do  poprzedniej  wersji  ADO  gdzie 
obiekt transakcji był zawarty w obiekcie połączenia. 

Przykład otwarcia transakcji:

    Private dbTemp As New SqlClient.SqlConnection
 

 

 

 

Private 

trTemp 

As 

System.Data.SqlClient.SqlTransaction

    Private cmdTemp As New SqlClient.SqlCommand
    Private bTran As Boolean
Private 

Sub 

btOtwarcie_Click(ByVal 

sender 

As 

System.Object, _

                                 ByVal e As System.EventArgs) _
                                 Handles btOtwarcie.Click        

background image

 

 

82

Transakcje w ADO.NET

• Try

// obsługa wyjątków

            If Trim(dbTemp.ConnectionString) = "" Then
             dbTemp.ConnectionString = txtConnStr.Text
            End If
                        If  dbTemp.State  =  ConnectionState.Closed 

Then

            dbTemp.Open()
            End If
      If Not 

bTran

 Then  

// kontrola otwarcia transakcji

       trTemp = dbTemp.BeginTransaction()
        bTran = True
     MsgBox("Transakcja została pomyślnie otwarta!", _ 
   MsgBoxStyle.Information)
            End If

background image

 

 

83

Transakcje w ADO.NET

Catch ex As Exception

                        MsgBox(ex.ToString, 

MsgBoxStyle.Exclamation)

    End Try
 End Sub

• Nie  można  otwierać  wielu  równoległych  lub 

zagnieżdżonych transakcji. 

• W  obiekcie  klasy 

SqlTransaction

    nie  ma 

żadnego 

mechanizmu 

kontrolującego 

stan 

transakcji  (czy  jest  już  otwarta,  zatwierdzona 
itp.); do tego celu stosowana jest zmienna 

bTran

 

która pozwala kontrolować otwarcie transakcji. 

background image

 

 

84

Transakcje w ADO.NET

• Kod 

przedstawiający 

zatwierdzenie 

otwartej 

transakcji:

Private Sub btCommTran_Click(ByVal sender As _
System.Object, ByVal e As System.EventArgs) _

            Handles btCommTran.Click
        Try            

If Not bTran Then

MsgBox("Transakcja nie została otwarta!", _ 
MsgBoxStyle.Exclamation)
                Exit Sub
            End If
            

trTemp.Commit()

            bTran = False

background image

 

 

85

Transakcje w ADO.NET

• Kod  przedstawiający  zatwierdzenie  otwartej  transakcji 

(c.d.):

MsgBox("Transakcja została pomyślnie zatwierdzona!", _

  MsgBoxStyle.Information)

        Catch ex As Exception
         MsgBox(ex.ToString, MsgBoxStyle.Exclamation)
        End Try

End Sub

• Do wycofania transakcji wykorzystujemy metodę 

Rollback

 :

Private Sub btRollTran_Click(ByVal sender As System.Object, 

_

                                 ByVal e As System.EventArgs) _
                                 Handles btRollTran.Click
        

background image

 

 

86

Transakcje w ADO.NET

• Kod przedstawiający wycofanie transakcji (c.d.):

       Try

             If Not bTran Then
   MsgBox("Transakcja nie jest otwarta!", _
  MsgBoxStyle.Exclamation)
                Exit Sub
            End If            

trTemp.Rollback()

     bTran = False
      MsgBox("Transakcja została wycofana!", _
    MsgBoxStyle.Information)

 

background image

 

 

87

Transakcje w ADO.NET

Catch ex As Exception

     MsgBox(ex.ToString, MsgBoxStyle.Exclamation)
        End Try

End Sub

Pomiędzy  otwarciem  a  zatwierdzeniem  transakcji 
muszą być wykonane jakieś operacje:

Private 

Sub 

btWykKom_Click(ByVal 

sender 

As 

System.Object, _

ByVal e As System.EventArgs) Handles btWykKom.Click
  cmdTemp.Connection = dbTemp

cmdTemp.Transaction = trTemp

             cmdTemp.CommandText = txtKom1.Text
             cmdTemp.ExecuteNonQuery()
End Sub

background image

 

 

88

Transakcje w ADO.NET

• Transakcję  należy  „podłączyć”  do  obiektu 

typu 

SqlCommand

• W  przedstawionych  przykładach  transakcja 

została sztucznie rozdzielona na poszczególne 
etapy; w rzeczywistości wszystko wykonuje się 

ramach 

jednej 

metody, 

przy 

czym 

wyświetlanie  komunikatów  po  zakończeniu 
poszczególnych etapów jest niedopuszczalne. 

• Ponieważ  transakcja  blokuje  jedną  lub  wiele 

tabel  na  których  wykonywane  są  operacje, 
należy przestrzegać następujących zasad: 

– podczas  transakcji  niedopuszczalna  jest 

żadna interakcja z użytkownikiem, 

background image

 

 

89

Transakcje w ADO.NET

– należy   wykonywać  tylko  konieczne  w 

ramach transakcji operacje,

– należy  starać  się  utrzymywać  ustalony 

porządek  w  wykonywaniu  operacji  na 
wielu 

tabelach, 

co 

 

pomaga 

zapobieganiu  tzw. 

Deadlocków,

  czyli 

sytuacji  kiedy  dwie  transakcje  blokują 
sobie nawzajem tabele.

background image

 

 

90

    

    

Private dbTemp As New SqlClient.SqlConnection

Private dbTemp As New SqlClient.SqlConnection

    

    

Private trTemp As System.Data.SqlClient.SqlTransaction

Private trTemp As System.Data.SqlClient.SqlTransaction

    

    

Private cmdTemp As New SqlClient.SqlCommand

Private cmdTemp As New SqlClient.SqlCommand

    

    

Private bTran As Boolean

Private bTran As Boolean

 

 

Private 

Sub 

btCalTran_Click(ByVal 

sender 

As 

Private 

Sub 

btCalTran_Click(ByVal 

sender 

As 

System.Object, _

System.Object, _

 

 

ByVal e As System.EventArgs) Handles btCalTran.Click

ByVal e As System.EventArgs) Handles btCalTran.Click

       

       

 

 

Try

Try

            

            

dbTemp.ConnectionString = txtConnStr.Text

dbTemp.ConnectionString = txtConnStr.Text

            

            

dbTemp.Open()

dbTemp.Open()

trTemp  =  dbTemp.BeginTransaction() 

trTemp  =  dbTemp.BeginTransaction() 

‘Rozpoczęcie 

transakcji

            

            

bTran = True

bTran = True

             

             

cmdTemp.Connection = dbTemp

cmdTemp.Connection = dbTemp

            

            

cmdTemp.Transaction = trTemp

cmdTemp.Transaction = trTemp

cmdTemp.CommandText  =  txtKom1.Text   

cmdTemp.CommandText  =  txtKom1.Text    'Wykonujemy 

komendy

 

 

cmdTemp.ExecuteNonQuery()

cmdTemp.ExecuteNonQuery()

background image

 

 

91

 

 

 

 

trTemp.Commit() 

trTemp.Commit()  ‘Zatwierdzenie transakcji

            

            

bTran = False

bTran = False

             

             

dbTemp.Close()

dbTemp.Close()

MsgBox("Transakcja została wykonana pomyślnie!", _

MsgBox("Transakcja została wykonana pomyślnie!", _

 

 

MsgBoxStyle.Information)

MsgBoxStyle.Information)

         

         

Catch 

Catch 

ex As Exception

ex As Exception

If  bTran  Then         

If  bTran  Then         

‘Wycofanie  transakcji  w  przypadku 

błędu

                

                

trTemp.Rollback()

trTemp.Rollback()

                

                

bTran = False

bTran = False

     

     

End If

End If

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

MsgBox(ex.ToString, 

MsgBox(ex.ToString, 

MsgBoxStyle.Exclamation)

MsgBoxStyle.Exclamation)

        

        

End Try

End Try

 

 

End Sub

End Sub

background image

 

 

92

Transakcje w ADO.NET

• Metoda 

Save

  obiektu  typu 

SqlTransaction

  pozwala 

na  zapisanie  tzw.  punktu  zapisu  (

savepoint

),  do 

którego    przy  wykonywaniu  operacji 

Rollback

 

wycofujemy operacje:

Private 

Sub 

btSave_Click(ByVal 

sender 

As 

System.Object, _

ByVal e As System.EventArgs) Handles btSave.Click
        Try 
  ...................................

trTemp.Save("Punkt  zapisu  #1")     

'Zapisanie  punktu 

zapisu

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

'Wycofanie do punktu zapisu

 trTemp.Rollback("Punkt zapisu #1")  

background image

 

 

93

Transakcje w ADO.NET

• Właściwość  IsolationLevel.  obiektu  SqlTransaction 

pozwala  ustalić  sposób  blokowania  danych  w  trakcie 
transakcji  na  poziomie  połączenia.  Zawiera  ona 
następujące elementy:
 Chaos  -  nie  zatwierdzone  zmiany  z  transakcji  o 

wyższym  poziomie  IsolationLevel  nie  mogą  być 
nadpisane,

 ReadCommitted  -  współdzielone  blokowania  są 

utrzymywane  dopóki  dane  są  czytane,  przez  co 
unika 

się 

tzw. 

dirty 

reads 

czyli 

czytania 

zmodyfikowanych  przez  inną  transakcję  danych 
których 

modyfikacja 

nie 

została 

jeszcze 

zatwierdzona. Ten sposób blokowania nie zapobiega 
jednak tzw. non-repeatable reads ani phantom data. 

background image

 

 

94

Transakcje w ADO.NET

 ReadUncommitted - przy tym blokowaniu dirty 

reads  jest  możliwe.  Połączenie  nie  ustawia 
żadnych  współdzielonych  blokowań  i  ignoruje 
wyłączne blokowania (exclusive locks). 

 RepeatableRead - ustawiane są blokowania na 

wszystkich  danych  które  są  używane  w  danej 
komendzie  nie  pozwalając  na  modyfikacje 
przez  innych  użytkowników.  Zapobiega  to  tzw. 
non-repeatable  reads  czyli  sytuacji  kiedy 
transakcja  czyta  wielokrotnie  jakieś  dane  i 
pomiędzy  tymi  odczytami  inna  transakcja 
zmodyfikowała te dane. Ten sposób blokowania 
nie zapobiega jednak tzw. phantom data. 

background image

 

 

95

Transakcje w ADO.NET

 Serializable  -  ustawiane  jest  na  obiekcie  typu 

DataSet  zapobiegając  modyfikacji  i  dodawania 
rekordu  do  DataSet  dopóki  transakcja  nie  jest 
zatwierdzona.  Może  zapobiec  tzw.  phantom  data 
czyli  sytuacji  kiedy  jedna  transakcja  modyfikuje 
rekordy  z  danego  zakresu  a  druga  transakcja 
wprowadza rekord do tego zakresu. 

 Unspecified - inny IsolationLevel niż ten który jest 

w danej chwili używany, ale który nie może być w 
tym momencie ustalony.

• Blokowanie danych w transakcji nie może naruszyć  

integralności danych.

 

background image

 

 

96

Transakcje w ADO.NET

• Transakcje są użytecznym elementem biblioteki 

ADO.Net, jednak należy z nich korzystać tylko w 
razie 

konieczności, 

pamiętając 

ograniczeniach które ze sobą niosą. 

• Klasa 

SqlTransaction

 nie daje takich możliwości 

jak  transakcje  wykonywane  na  poziomie  SQL 
Serwera,  gdyż  nie  pozwala  np..  na  stosowanie 
transakcji zagnieżdżonych. 

• Lepsze  efekty  można  często  uzyskać  realizując 

transakcje  nie  na  poziomie  ADO.Net,  ale  w 
procedurze wsadowej.

background image

 

 

97

Zapis i odczyt pól BLOB

• Binary  large  objects  (BLOBs) 

mogą  zawierać 

duże ilości danych co uniemożliwia zmieszczenie 
danych  w  pojedynczym  wierszu  który  mógłby 
zostać przetworzony przez 

DataReader. 

• Problem  ten  może  rozwiązać

 

przeciążona 

metoda

  ExecuteReader 

przyjmująca  argument 

CommandBehavior. 

SequentialAccess, 

która 

modyfikuje  zachowanie  obiektu  DataReader  tak 
że przyjmuje on sekwencyjne dane. 

• Ważna  jest  kolejność  zwracanych  pól,  ponieważ 

SequentialAccess 

modyfikuje 

DataReader

  tak 

aby zwracać dane w kolejności, wobec tego dane 
raz przeczytane mogą być już niedostępne.

background image

 

 

98

Zapis i odczyt pól BLOB

SqlConnection con = new SqlConnection("Data 
Source = localhost;Integrated Security=SSPI; 
Initial Catalog = test;");
SqlCommand ob = new SqlCommand("SELECT 
id, obrazek FROM obrazy", con);

FileStream fs; 
BinaryWriter bw;. 

// zapis obrazka do pliku (*.bmp).

// ustawienie rozmiaru bufora

int bufferSize = 100;

 

// tablica wypełniana przez GetBytes

byte[] outbyte = new byte[bufferSize];

background image

 

 

99

Zapis i odczyt pól BLOB

// wartości zwrócone prze GetBytes

long retval;

// pozycja początkowa na wyjściu BLOB

long startIndex = 0;
string id = ""; 
con.Open();

SqlDataReader myReader =ob.ExecuteReader 

(CommandBehavior.SequentialAccess);
while (myReader.Read())

{
id = myReader.GetString(0);

background image

 

 

100

Zapis i odczyt pól BLOB

//utworzenie pliku wyjściowego.

fs = new FileStream(”plik" +id + ".bmp", 
FileMode.OpenOrCreate, FileAccess.Write);
bw = new BinaryWriter(fs);
startIndex = 0;

// odczyt bajtów i zachowanie ich w outbyte

retval = myReader.GetBytes(1, startIndex, 
outbyte, 0, bufferSize);

// dalszy odczyt i  zapisywanie danych.

while (retval == bufferSize)

{    bw.Write(outbyte);

bw.Flush(); 

background image

 

 

101

Zapis i odczyt pól BLOB

startIndex += bufferSize;
retval = myReader.GetBytes(1, startIndex, 

outbyte, 0,  bufferSize);

}

// zapis reszty do bufora

bw.Write(outbyte, 0, (int)retval - 1);
bw.Flush();

bw.Close(); 

// zamkniecie pliku

fs.Close();

}

myReader.Close();
con.Close();

background image

 

 

102

Pozyskiwanie informacji o 

strukturach danych

SqlConnection con = new 

SqlConnection("server=localhost; 
database=Northwind;uid=sa;pwd=;");

 string SQL = "SELECT TABLE_NAME FROM 

      

INFORMATION_SCHEMA.TABLES " +  "WHERE 
TABLE_TYPE = 'BASE TABLE' " +

       "ORDER BY TABLE_NAME";
 SqlDataAdapter schemaDA = new 

SqlDataAdapter(SQL,con);

 DataTable schemaTable = new DataTable();
 schemaDA.Fill(schemaTable);

Struktura  danych    włącza  bazy  danych  lub  dostępne 
katalogi  z  danych  źródłowych,  tabel  i  widoków, 
ograniczenia  tabel  w  bazie  danych,  itd.  Informacje  o 
strukturach 

danych 

można 

uzyskać 

używając 

jakiegokolwiek  dostawcy  danych  przy  pomocy  metody 

SchemaTable

background image

 

 

103

Pobieranie danych w postaci 

XML

• Dokument  XML  jest  hierarchiczną  bazą  danych, 

dlatego też można wczytywać informacje z pliku (lub 
strumienia) 

XML

  do 

DataSet

  przy  pomocy  metody 

ReadXML().

 

• Metoda ta przyjmuje parametr 

XmlReadMode

, który 

mówi  jak  mają  być  traktowane  informacje  o 
strukturze tabeli (

Xml Schema

), jeśli zawarte są one 

w  dokumencie  –  dane  te  opisują  tabele  znajdujące 
się w pliku – np. nazwy kolumn, typy danych itp. 

• Obiekt  DataSet  posiada  także  możliwość  zapisu 

danych  do  formatu,  XML  przy  pomocy  metody 

WriteXml(),

  której  parametr  określa  czy  chcemy 

zapisać  wszystkie  dane,  czy  tylko  strukturę  tabeli 
(

Schema

), czy tylko same dane. 

background image

 

 

104

string xmlDoc = @"<?xml version='1.0'?>

    <books>
          <book>

   <title>Przykład odczytu i 

zapisu  XML</title>

         </book>
   </books>";

// Załadowanie  obiektu StringReader

StringReader src = new StringReader(xmlDoc);

// Tworzenie nowego obiektu DataSet i odczyt XML

DataSet dset = new DataSet();
dset.ReadXml(src);

// Zapis DataSet  jako nowy plik XML

dset.WriteXml(@"C:\dokumenty\plik.xml");

Pobieranie danych w postaci 

XML cd.


Document Outline