ADO .NET 2005

advertisement
ADO .NET
1
Model dostępu do danych
za pomocą ADO.NET
Strona ASP.NET
ADO.NET
OLE DB
ODBC
SQL
Jet
itd.
2
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,
3
Oracle, plik XML itp.
Ogólny model dostępu do danych
4
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.
5
ADO.NET – ogólna architektura cd.
6
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
7
danych w źródle na podstawie DataSet;
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
8
rodzaju baz danych jakich używa dana aplikacja.
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ą
9
Microsoft SQL Server 6.5 i wcześniejszych
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
10
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.
11
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,
12
DataColumn, DataRelation.
Ogólny schemat DataSet
DataSet
ExtendedProperties
RelationsCollection
TableCollection
DataTable
ChildRelations
Columns
DataColumns
Constraints
DefaultView
ExtendedProperties
ParentRelations
PrimaryKeys
Rows
DataRows 13
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).
14
Budowa obiektu DataSet
15
Właściwości obiektu DataTable
Własciwość
Opis
Jeżeli jej wartością jest True, to w czasie porównywania napisów
CaseSensitve przechowywanych w tabeli rozróżniane są małe i duże litery.
HasErrors
PrimaryKey
Jeżeli jej wartością jest True, to oznacza, że przynajmniej jeden element
tabeli zawiera nieprawidłową wartość.
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.
16
Metody obiektu DataTable
Metoda
AcceptChanges
NewRow
Opis
Zatwierdza wszystkie zmiany dokonane w tabeli.
Dodaje nowy wiersz do tabeli.
RejectChanges Odrzuca wszystkie zmiany dokonane w tabeli.
GetChanges
Clone
Wyniku jej działania otrzymujemy obiekt DataTable zawierający
elementy, w których nastąpiły zmiany.
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.
17
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.
18
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.
19
Właściwości obiektu DataRow
Właściwości
HasErrors
Item
RowError
RowState
Table
Opis
Jeżeli jej wartością jest True, to oznacza, że przynajmniej jeden
element wiersza zawiera nieprawidłową wartość.
Pobranie lub ustawienie elementu (wskazanego przez argument) w
tym wierszu.
Pobranie lub ustawienie komunikatu o błędzie danego wiersza.
Określa aktualny stan wiersza (czy zmodyfikowany, usunięty,
dodany).
Pobranie (tylko do odczytu) właściwości obiektu DataTable, do
którego należy dany wiersz.
20
Metody obiektu DataRow
Metoda
Opis
AcceptChanges
Zatwierdza wszystkie zmiany wprowadzone w wierszu.
ClearErrors
Usuwa błędy ustawione dla danego wiersza.
Delete
ToString
RejectChanges
Usuwa wiersz tabeli
Przedstawia obiekt w postaci napisu
Odrzuca wszystkie zmiany, które wystąpiły w danym
wierszu.
GetType
GetColumnError
Tworzy obiekt z informacjami o typie obiektu
Wynikiem działania jest komunikat o błędzie kolumny
skojarzonej z danym argumentem.
21
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).
22
Właściwości obiektu DataColumn
Właściwości
Opis
Określa czy w kolumnie może wystąpić wartość pusta, Null.
AllowDBNull
AutoIncrement Określa czy wartość w kolumnie, podczas dodawania nowych wierszy
jest automatycznie zwiększana.
Caption
ColumnName
DataType
DefaultValue
Pobranie lub ustawienie wyświetlanej nazwy kolumny.
Pobranie lub ustawienie nazwy kolumny.
Pobranie lub ustawienie, jakiego typu dane mogą znaleźć się w kolumnie.
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ć).
23
Metody obiektu DataColumn
Metoda
Equals
GetType
Opis
Określa czy obiekt jest równy obiektowi przekazanemu w
argumencie.
Tworzy obiekt klasy Type, zawierający informacje o typie
obiektu
ToString
Przedstawia obiekt w postaci napisu
24
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
25
DataSet.RejectChanges.
Relacje w obiekcie DataSet
26
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.Tables("tabela1").Columns("AdresID"),
ds.Tables("tabela2").Columns("AdresID");

Najczęstszą metodą tworzenia obiektu DataSet jest
wczytanie jego struktury z pliku XML.
27
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;
28
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";
29
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 30
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.
31
Właściwości klasy DataSet
HasErrors
Locale
Prefix
Informuje czy dane zapisane w którymkolwiek
z wierszy przechowywanych w danym
obiekcie DataSet zawierają błędy.
Informacje lokalne używane przy
porównywaniu łańcuchów znaków.
Właściwość ta zwraca obiekt klasy
CultureInfo.
Synonim XML określający przestrzeń
nazw danego obiektu DataSet.
Relations Obiekt klasy DataRelationCollection reprezentujący
wszystkie relacje występujące pomiędzy tabelami
przechowywanym w danym obiekcie DataSet.
32
Właściwości klasy DataSet
Site
Zwraca interfejs ISite do obiektu klasy DataSet
(służący do wiązania komponentów z obiektami
zawierającymi dane).
Tables
Obiekt klasy DataTableCollection
reprezentujący wszystkie tabele przechowywane
w danym obiekcie DataSet.
Xml
Dane przechowywane w danym obiekcie
DataSet, zapisane w formacie XML.
XmlSchema
Schemat XML wykorzystywany w danym
obiekcie DataSet.
33
Właściwości klasy DataSet
AcceptChanges Zatwierdza wszelkie modyfikacje wprowadzone
w danym obiekcie DataSet.
BeginInit
Rozpoczyna inicjalizację obiektu DataSet w
trakcie działania programu.
Clear Usuwa wszystkie wiersze ze wszystkich tabel
zapisanych w danym obiekcie DataSet.
Clone Tworzy obiekt DataSet stanowiący dokładną
kopię danego obiektu, lecz bez danych.
Copy
Tworzy obiekt DataSet stanowiący dokładną
kopię danego obiektu i zawierający wszystkie
dane.
34
Właściwości klasy DataSet
EndInit
GetChanges
HasChanges
InferXmlSchema
Marge(DataSet)
Zakańcza proces inicjalizacji obiektu
DataSet w trakcie działania programu.
Tworzy nowy obiekt klasy DataSet
zawierający wyłącznie dane, które zostały
zmodyfikowane.
Określa czy informacje w danym obiekcie
DataSet uległy jakimkolwiek zmianom.
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.
Łączy dany obiekt DataSet z obiektem
podanym jako argument wywołania
metody.
35
Właściwości klasy DataSet
ReadXmlSchema Tworzy strukturę danych na podstawie schematu
XML.
RejectChanges Odtwarza wszelkie zmiany jakie zostały
wprowadzone w obiekcie DataSet.
ResetRelations Przywraca domyślną wartość właściwości
Relations.
ResetTables Przywraca domyślną wartość właściwości Tables.
ShouldSerializeRelations Informuje czy wartość właściwości Relations
powinna zostać zachowana.
ShouldSerializeTables Informuje czy wartość właściwości Tables
powinna zostać zachowana.
36
Właściwości klasy DataSet
WriteXml
Zapisuje zawartość obiektu
DataSet w formacie XML.
WriteXmlSchema Zapisuje strukturę obiektu
DataSet w formacie XML.
37
Zdarzenia klasy DataSet
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.
38
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
39
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.
40
Połączenie ze źródłem danych

Metody zawarte w
dostawcy:

DataAdapter dostępne są dla
OLEDB w klasie
System.Data.OleDb.OleDbDataAdapter

SQL Server w klasie
System.Data.SqlClient.SqlDataAdapter
41
Model obiektu DataAdapter
DataAdapter
DeleteCommand
InsertCommand
SelectCommand
UpdateCommand
TableMappings
ColumnMappings
Metody Command, obiektu DataAdapter służą do modyfikacji
danych w obiekcie DataSet.
Kolekcja TableMappings określa sposób odwzorowania w
42
obiektach DataSet tabel i kolumn ze źródła danych.
Metody obiektu DataAdapter
Metoda
Opis
Fill
Dodaje lub modyfikuje wiersze w obiekcie
DataSet
FillSchema
Dodaje obiekt DataTable do obiektu DataSet i
konfiguruje schemat tabeli
GetFillParameters
Zwraca tablicę obiektów
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
43
Command
IDataParameter
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
44
same właściwości jak zdarzenie RowUpdated
Zdarzenia obiektu DataAdapter
- przykład
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(onRowUpdating);
DA.RowUpdated += new
SqlRowUpdatedEventHandler(onRowUpdated);
DA.FillError += new
FillErrorEventHandler(FillErrorHandler);
DataSet Ds = new DataSet();
45
Zdarzenia obiektu DataAdapter
- przykład
//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");
46
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();
47
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
48
System.Data.SqlClient.SqlConnection
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
49
niezawodności aplikacji.
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.
50
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.
51
Połączenie z bazą danych SQL
SqlConnection connection1 = new SqlConnection();
connection1.ConnectionString="userid=sa;datasource=
\"WINDOWSXP\\SQLDB\";persist "+ "security
info=False;initial catalog=northwind";
connection1.Open();
// Utworzenie pierwszej puli (A).
SqlConnection connection2 = new SqlConnection();
connection2.ConnectionString="userid=sa;datasource=
\"WINDOWSXP\\SQLDB\";persist "+ "security
info=False;initial catalog=pub";
connection2.Open();
// Utworzenie drugiej puli (B)
52
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("Provider=SQLOLEDB;Data
Source=localhost;" + "Integrated Security=SSPI;Initial
Catalog=northwind"); nwindConn.Open();
• .NET Framework Data Provider for ODBC do tworzenia
połaczeń korzysta z OdbcConnection
OdbcConnection Con = new
OdbcConnection("Driver={SQL Server};Server=localhost;"
+ "Trusted_Connection=yes;Database=northwind");
Con.Open();
53
Połączenie z innymi źródłami
danych
• .NET Framework Data Provider for Oracle tworzy
połączenie przy pomocy OracleConnection
OracleConnection Con=newOracleConnection("Data
source=MyOracleServer;
Integrated Security=yes;"); nwindConn.Open();
54
Właściwości obiektu
Connection
Właściwość
Opis
ConnectionString
Łańcuch znaków służący do utworzenia połączenia
ConnectionTimeout
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
55
Metody obiektu Connection
Metoda
Opis
BeginTransaction
Rozpoczyna transakcję z bazy danych
Close
Zamyka połączenie z bazą danych
Open
Otwiera połączenie z bazą danych
56
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
57
Model obiektu Command
Command
Connection
Properties
Parameters
Parameter
Properties
Property
58
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
59
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
60
obejrzenie wszystkich wierszy wyniku.
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
Obiekt Transaction używany przez Command
Transaction
UpdateRowSource
Liczba wierszy objętych poleceniem SQL; w
przypadku poprawnego polecenia wartość 61
ta
wynosi 1
Metody obiektu Command
Metoda
Opis
Cancel
Przerywa wykonanie polecenia
CreateParameter
Tworzy obiekt Parameter
ExecuteNonQuery
Wykonuje polecenie SQL, które nie zwraca
żadnych danych
ExecuteReader
Zwraca obiekt DataReader zawierający
dane uzyskane w wyniku wykonania
polecenia SQL
62
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.
63
Dostęp do danych
SqlDataReader myReader = myCommand. 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).
64
Dostęp do danych

Jedno wykonanie metody Read obiektu DataReader, zwraca
jeden rekord danych.
while(reader.Read())
{
myString = reader.Item(0).ToString();
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.
65
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
66
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
RecordsAffected
Okresla ilość wierszy objętych wynikami
działania polecenia SQL; w przypadku
poprawnego wykonania zwraca 1, w
67
przypadku błędu zwraca -1
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
Zwraca wartość kolumny jako String
GetString (indeks)
IsDBNull
Metoda
stosowana
do
nieistniejących wartości
przedstawiania
NextResult
W przypadku wykorzystania wyników
wsadowego polecenia SQL, metoda ta
przesuwa obiekt do następnego rekordu
Read
Przesuwa obiekt do następnego rekordu
68
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.
69
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
70
Dostęp do danych - przykład
c.Connection = polaczenie;
polaczenie.Open();
// definiowanie obiektu Connection
// 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];
dr.GetValues(rg);
dr.Close();
polaczenie.Close();
// utworzenie tablicy
// zapisanie rekordu w tablicy
// zamknięcie czytnika danych
// zamknięcie połączenia
conflict.Display(dbcex.Row, rg); }
// wyświetlenie danych w kontrolce użytkownika
71
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();
72
Wykonywanie operacji SQL nie
zwracających danych
(INSERT,UPDATE,DELETE) cd.
Program zwraca numery wierszy dla których zostało wykonane
polecenie DELETE.
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().ToString());
con.Close()
73
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.
74
Model przechwytywania
wyjątków – klasa SQL Exception
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();
}
75
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("server=localhost;
database=Northwind;uid=sa;pwd=;");
SqlCommand cmd = new
SqlCommand(”Najdrozsze_produkty", con);
cmd.CommandType = CommandType.StoredProcedure;
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
while(reader.Read())
{
Console.WriteLine("{0} - {1:C}",
reader.GetString(0),reader.GetDecimal(1));
}
con.Close();
76
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 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();
SqlDataReader reader = cmd.ExecuteReader();
77
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();
78
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
79
wartość).
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();
80
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
81
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
82
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.
83
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
84
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
85
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)
86
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()
87
End Sub
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,
88
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.
89
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 btCalTran_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btCalTran.Click
Try
dbTemp.ConnectionString = txtConnStr.Text
dbTemp.Open()
trTemp = dbTemp.BeginTransaction()
‘Rozpoczęcie transakcji
bTran = True
cmdTemp.Connection = dbTemp
cmdTemp.Transaction = trTemp
cmdTemp.CommandText = txtKom1.Text 'Wykonujemy komendy
90
cmdTemp.ExecuteNonQuery()
trTemp.Commit()
‘Zatwierdzenie transakcji
bTran = False
dbTemp.Close()
MsgBox("Transakcja została wykonana pomyślnie!", _
MsgBoxStyle.Information)
Catch ex As Exception
If bTran Then
‘Wycofanie transakcji w przypadku błędu
trTemp.Rollback()
bTran = False
End If
MsgBox(ex.ToString, MsgBoxStyle.Exclamation)
End Try
End Sub
91
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")
92
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.
93
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.
94
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.
95
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.
96
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.
97
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];
98
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);
99
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();
100
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();
101
Pozyskiwanie informacji o
strukturach danych
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
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);
102
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. 103
Pobieranie danych w postaci XML cd.
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");
104
Download