1
ADO .NET
2
Model dostępu do danych
za pomocą ADO.NET
Strona ASP.NET
ADO.NET
OLE DB
ODBC
SQL
Jet
itd.
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.
4
Ogólny model dostępu do
danych
5
ADO.NET – warstwy
dostępu do danych
W aplikacjach korzystających
z
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.
6
ADO.NET – ogólna
architektura cd.
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;
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.
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ę
w
przestrzeni
nazw
System.Data.OleDb.
stosowany jest dla aplikacji pracujących z wersją
Microsoft SQL Server 6.5 i wcześniejszych
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
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.
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.
13
Ogólny schemat DataSet
DataSet
ExtendedProperties
RelationsCollection
TableCollection
DataTable
ChildRelations
Columns
Constraints
DefaultView
ExtendedProperties
ParentRelations
PrimaryKeys
Rows
DataRows
DataColumns
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).
15
Budowa obiektu DataSet
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.
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.
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.
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.
20
Właściwości obiektu
DataRow
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.
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).
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ć).
24
Metody obiektu
DataColumn
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
.
26
Relacje w obiekcie DataSet
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
.
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;
29
Tworzenie obiektu
DataSet w kodzie
programu
//Zdefiniowanie
struktury
tabeli(Columns)
i
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";
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
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.
32
Właściwości klasy DataSet
33
Właściwości klasy DataSet
34
Właściwości klasy DataSet
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
36
Właściwości klasy DataSet
37
Właściwości klasy DataSet
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
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
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.
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
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.
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
w
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
44
Zdarzenie
Opis
FillError
Zdarzenie
zachodzi
gdy
podczas
wykonywania
metody
Fill
zostanie
zgłoszony błąd. Argumentem jest obiekt
FillErrorEventArgs.
RowUpdated
Zachodzi
w
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
z
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
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
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
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();
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
i
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
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.
50
Połączenie z bazą danych
SQL
• W
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.
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ń
w
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.
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)
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();
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();
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
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
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
INSERT, DELETE, UPDATE 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
58
Model obiektu Command
Command
Connection
Parameters
Properties
Properties
Parameter
Property
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
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.
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
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
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.
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).
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
.
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
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,
w
przypadku błędu zwraca -1
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
W
przypadku
wykorzystania
wyników
wsadowego
polecenia
SQL, metoda ta przesuwa obiekt do
następnego rekordu
Read
Przesuwa obiekt do następnego
rekordu
69
Dostęp do danych -
przykład
Wykorzystanie obiektów
Connection, Command
oraz
DataReader
w celu wyświetlenia informacji o
błędnych
wierszach
zawartych
w
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.
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
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
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();
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.
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.
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
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();
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();
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();
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ść).
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();
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
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
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.
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
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
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)
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
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ę
w
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,
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
w
zapobieganiu tzw.
Deadlocków,
czyli
sytuacji kiedy dwie transakcje blokują
sobie nawzajem tabele.
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()
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
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")
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.
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.
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.
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
o
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.
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.
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];
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);
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();
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();
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
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.
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.