3 ADO NET


Warstwa dostępu do danych
" Architektura ADO.NET
" Obiekty DataSet, Connection, Command, DataAdapter i ich
współdziałanie
" Praca w trybie połączonym: DataReader
Mainframe
" Praca w trybie odłączonym: DataSet
" Modyfikacje zródła danych
Directory
" Obsługa procedur pamiętanych w b.d.
XML
RDBMS
" Integracja z XML
" Transakcje Email i
wiadomości
" LINQ, Entity Framework
ADO
System plików
" ADO.NET Data Services
OLE DB
Problemy
" Modele programistyczne
 Połączeniowy (connected)  oparcie o otwarte
połączenia do systemu bazy danych (OLE DB, ADODB)
 Bezpołączeniowy (disconnected)  pytanie/odpowiedz,
bez-stanowy między zapytaniami (HTTP)
" Obsługa stanu
Tryb połączeniowy
" W modelu klient  serwer każdy klient łączy się z bazą podczas startu
aplikacji i zwalnia połączenie podczas jej zamykania
" Serwer musi utrzymywad oddzielne połączenia dla każego klienta
Możliwe niepotrzebne zużycie
idle
zasobów
busy
" Serwery bazodanowe zapewniają
dostęp do kursora
idle
Serwer
przechowującego stan aktualnego
Połączenia
Klienci
wiersza
 Dostęp do danych
 Przesuwanie się przez MoveNext
oraz MovePrevious
Serwer
rs
Klient
Tabele
Kursor
Wyniki zapytania
Tryb połączeniowy
Zalety
Wady
" Połączenie tworzymy tylko raz " Niepotrzebne zużycie zasobów
" Możemy ustawiać zmienne " Problemy ze skalowalnością
powiązane z  sesją
" Nie dostosowany do aplikacji webowych
" Szeroki dostęp do mechanizmów
" Użytkownicy się nie wylogowują
zabezpieczajacych dostarczonych
" Wahająca się liczba użytkowników
przez bazę danych
" Nie dostosowany do aplikacji
" Pierwszy wiersz zapytania dostępny
wielowarstwowych
od razu
Tryb bezpołączeniowy
" Połączenia są zwalniane zaraz po wykorzystaniu
" Obiekty danych wykorzystywane są również po zwolnieniu połączenia
" Połączenie jest nawiązywane by zapisad zmiany do bazy
idle
Zasoby są używane tylko gdy są Serwer
potrzebne
busy
Połączenia
" Dane są dostarczane do klienta w
idle
jednej operacji
Klienci
" Wyniki zapytania przechowywane w
Serwer
pamięci klienta
Klient
" Zasoby serwera są zwalniane
rs
" Klient zarządza danymi w trybie off-
line
" Ponowne połączenie z bazą by
Kursor Wyniki zapytania
Tabele
zapisać zmiany
Tryb bezpołączeniowy
Zalety
Wady
" Mniejsze zużycie zasobów serwera " Otwieranie i zamykanie połączeń
jest kosztowne
" Modyfikacja danych jest szybsza i
bardziej elastyczna " Wczytywanie dużych ilości danych
jest czasochłonne
" Dane nie związane z połączeniem
" Zużycie zasobów po stronie klienta
" Aatwe przekazywanie między
warstwami " Mniej opcji zarządzania
bezpieczeńswem
" Wykorzystywane w aplikacjach
wielowarstwowych oraz webowych
Architektura ADO.NET
.NET Data Provider
DataSet
Tables
Connection
DataAdapter
DataTable
Transaction
SelectCommand
Fill
DataRowCollection
InsertCommand
Command
DataColumnCollection
Parameters
UpdateCommand
Update
ConstraintCollection
DeleteCommand
DataReader
DataRelationCollection
ReadXml
WriteXml
Database
XML
.NET data provider jest to zestaw klas, za pomocą których podłaczamy się do zródła danych
oraz pobieramy i aktualizujemy dane
ADO.NET Object Model
DataSet
Connection
DataTable
Command
DataColumn
Parameter
DataRow
DataReader
.NET Data
Provider
Transaction Constraint
DataAdapter
DataRelation
Klasa
Opis
Connection
Umożliwia nawiązanie połączenia z określonym zródłem danych
Command Wywołuje polecenie na zródle danych. Udostępnia kolekcję parametrów (Parameters) i zawsze
działa w kontekście otwartego połączenia (Connection)
DataReader
Udostępnia jednokierunkowy (rekord po rekordzie) strumień danych ze zródła, w trybie 'tylko do
odczytu'
DataAdapter Wypełnia DataSet danymi pochodzącymi ze zródła oraz umożliwia aktualizacje danych w zródle na
podstawie DataSet-u (kanał łączący obiekt DataSet z dostawcą danych)
ADO.NET Class hierarchy
IDbConnection
IDbCommand
" Interfejsy
IDbConnection
IDbTransaction
IDbCommand
IDataReader
IDbTransaction
IDataReader
" Abstrakcyjne klasy bazowe
DbConnection
DbConnection
DbCommand
DbCommand
DbTransaction
DbTransaction
DbDataReader
DbDataReader
...
" Implementacja specjalizowana
OleDb: implementacja dla OLEDB
Sql: implementacja dla SQL OleDbConnection SqlConnection OracleConnection
Server
OleDbCommand SqlCommand OracleCommand
Oracle: implementacja dla Oracle
OleDbTransaction SqlTransaction OracleTransaction
Odbc: implementacja dla ODBC
OleDbDataReader SqlDataReader OracleDataReader
Tworzenie połączenia
" Aańcuch połączenia (ang. connection string) - ciąg znaków zawierających
parametry konfiguracji połączenia
" SqlConnection
string strConn = "data source=localhost; " +
"initial catalog=northwind; integrated security=true";
SqlConnection conn = new SqlConnection(strConn);
" Parametry ConnectionString
 User ID: konto logowania SQL Server
 Connection timeout: dopuszczalny czas
 Password:
uzyskania połączenia
 &
 Data source: nazwa instancji SQL Server lub
nazwa komputera
 Initial catalog: nazwa bazy danych
 Integrated security; gdy True połączenie z SQL
serwerem na podstawie tożsamości konta procesu
ASP.NET
http://www.connectionstrings.com/
Połączenie: Tworzenie połączenia
public interface IDbConnection
{
string ConnectionString {get; set;}
int ConnectionTimeout {get;}
string Database {get;}
ConnectionState State {get;}
BeginTransaction 
IDbTransaction BeginTransaction();
Rozpoczyna tranzakcję
IDbTransaction BeginTransaction(IsolationLevel il);
void ChangeDatabase(string db);
ChangeDatabase  Zmiana
void Close();
bazy dla otrawtego połącznia
IDbCommand CreateCommand();
void Open();
}
ConnectionTimeout  Określenie czasu timeoutu Open, Close  Otwieranie i zamykanie
połączenia połączenia
Database  Nazwa bazy dla połączenia
State  Zwraca stan aktualnego połączenia: Broken, CreateCommand  Tworzy obiekt Command
Closed, Connecting, Executing, Fetching, or Open. powiązany z połączeniem
ConnectionString - zarządzanie
" Umieszczamy w sekcji pliku konfiguracyjnego
< configuration >
...
< connectionStrings >
< add name= Northwind providerName= System.Data.SqlClient
connectionString= server=(local);
integrated security=SSPI;database=Northwind / >
< /connectionStrings >
< /configuration >
private DbConnection GetDatabaseConnection ( string name )
{
ConnectionStringSettings settings =
ConfigurationManager.ConnectionStrings[name];
DbProviderFactory factory =
DbProviderFactories.GetFactory(settings.ProviderName );
DbConnection conn = factory.CreateConnection ( ) ;
conn.ConnectionString = settings.ConnectionString ;
return conn ;
}
Wydajne używanie połączeo
Blok using
try . . . catch . . . finally
try
try
{
{
using (SqlConnection conn =
new SqlConnection(source))
// Open the connection
{
conn.Open();
// Open the connection
DoSomething();
conn.Open ( ) ;
}
DoSomething();
catch ( SqlException ex )
}
{
}
//Log the exception
catch (SqlException e)
{
}
// Log the exception
finally
}
{
conn.Close ( ) ;
}
using  zapewnia wywołanie Dispose()
najwcześniej jak to możliwe, poprzez
zdeklarowanie używanych obiektów i określeniu
przez nawiasy {} zasięgu tych obiektów
Pula połączeo
" Connection pooling  proces utrzymywania otwartych połączeń i
ponownego ich reużycia dla uzytkownika lub kontekstu
" Parametry ConnectionString dla poolingu
 Connection Lifetime: długość oczekiwania połączenia na ponowne użycie
 Max Pool Size: maksymalna liczba połączeń
 Min Pool Size: Minimalna liczba połączeń
 Pooling: True/False
 &
cnNorthwind.ConnectionString = _
"Integrated Security=True;" & _
"Initial Catalog=Northwind;" & _
"Data Source=London;" & _
"Pooling=True;" & _
"Min Pool Size=5;" & _
"Connection Lifetime=120;"
ADO.NET  modele programowania
" ADO.NET zapewnia dostęp do obu typów
programowania
 Połączeniowy
" Używa obiektów Command i DataReader
" DataReader służy do odczytu w przód
" Zmiany/aktualizacje odbywają się przez obiekt Command
 Bezpołączeniowy
" Używa obiektów DataSet do przechowywania danych u klienta
" DataAdapter obsługuje komunikację miedzy obiektemDataSet a
serwerem
" Obiekty DataSet są niezależne od providera
" Obiekty DataSet są przechowywane oraz przesyłane przez XML
Obiekt Command
public interface IDbCommand
{
" Connection - referencja do obiektu
string CommandText {get; set;}
połączenia
int CommandTimeout {get; set;}
CommandType CommandType {get; set;}
" CommandType - typ polecenia
IDbConnection Connection {get; set;}
 Text  wyrażenie SQL
IDbTransaction Transaction {get; set;}
 StoredProcedure
UpdateRowSource UpdatedRowSource {get; set;}
IDataParameterCollection Parameters {get;}
" CommandText - w zależności od
wyboru typu plecenia:
void Cancel();
 Text  treść polecenia SQL
IDataParameter CreateParameter();
 StoredProcedure  nazwa procedury
int ExecuteNonQuery();
IDataReader ExecuteReader();
IDataReader ExecuteReader(CommandBehavior cb);
" Parameters
object ExecuteScalar();
 Parametry, z którymi zostanie
void Prepare();
wykonane zapytanie
// Note ExecuteXmlReader (SqlCommand only)
}
Metody wywołania obiektu Command
" Zapytanie nie zwraca wierszy
 Wywołanie ExecuteNonQuery
" Zwraca liczbę wierszy  dotkniętych przez zapytanie
 Zapytania DDL and DCL
" CREATE, ALTER, DROP, GRANT, DENY, REVOKE
 Zapytaia DML
" INSERT, UPDATE, DELETE
" Zapytanie zwraca pojedynczą wartośd
 Wywołanie ExecuteScalar
" ExecuteScalar zwraca typ Object
" Zapytanie zwraca wiersz
 Metoda ExecuteReader
" Zwraca obiekt DataReader
" Reader zależny od providera: SqlDataReader, OleDbDataReader
 DataReader
" Służy tylko do odczytu, możliwe przesuwanie tylko w przód
" Zapytanie zwraca XML
 ExecuteXmlReader  dostępny tylko dla SQL Server
Command - przykład
private void Demo()
{
SqlConnection con = new SqlConnection(
"Server=localhost; Database=Pubs; Integrated Security=SSPI" );
SqlCommand cmd = new SqlCommand(
"SELECT COUNT( * ) FROM Authors", con );
con.Open();
Console.WriteLine( cmd.ExecuteScalar() ); // Writes '23'
con.Close(); // Important!
}
Asynchroniczne wywołanie Command
" ADO.NET 2.0 wspiera tryb asynchroniczny
" Wykonanie poleceń w tle
IAsyncResult BeginExecuteReader (AsyncCallback callback)
IDataReader EndExecuteReader (AsyncResult result)
IAsyncResult BeginExecuteNonQuery (AsyncCallback callback)
int EndExecuteNonQuery (IAsyncResult result)
IAsyncResult BeginExecuteXmlReader (AsyncCallback callback)
IDataReader EndExecuteXmlReader (IAsyncResult result)
Asynchroniczny Command - przykład
...
public class Async {
SqlCommand cmd; //---- command which should be executed asynchronously
public void CallCmdAsync() {
SqlConnection conn = new SqlConnection(
"Data Source=(local)\\NetSDK...; Asynchronous Processing=true");
cmd = new SqlCommand("MyLongRunningStoredProc", conn);
cmd.CommandType = CommandType.StoredProcedure;
conn.Open();
//---- start asynchronous execution of command
cmd.BeginExecuteNonQuery(new AsyncCallback(AsyncCmdEnded), null);
...
}
Callback when query is finished
//---- callback method called at the end of the execution of command
public void AsyncCmdEnded(IAsyncResult result) {
//---- process result of command
int affectedRows = cmd.EndExecuteNonQuery(result);
...
}
}
Zapytania parametryzowane
<>
IDbCommand
" Command pozwala na definiowanie
parametrów wejściowych i wyjściowych
...
IDataParameterCollection
Parameters {get;}
IDataParameterCollection Parameters {get;}
...
Parameters *
" Parameter - pola
<>
 Name: nazwa parametru
IDataParameter
//----- Properties
 Value: wartość parametru
DbType DbType {get; set;}
 DbDataType: typ danych
ParameterDirection Direction {get; set;}
string ParamterName {get; set;}
 Direction: kierunek parametru
object Value {get; set;}
...
- Input
- Output
<>
- InputOutput
IDbDataParameter
- ReturnValue
//----- Properties
int Size {get; set;}
...
Zapytania parametryzowane - przykład
1. Zdefiniowanie zapytania
SQL Server: Identyfikacja parametru przez  @ (przykład: "@name")
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "DELETE FROM Empls WHERE EmployeeID = @ID";
2. Dodanie parametru
cmd.Parameters.Add( new OleDbParameter("@ID", OleDbType.BigInt));
3. Przypisanie wartości
cmd.Parameters["@ID"].Value = 1234;
cmd.ExecuteNonQuery();
Tryb połączeniowy: DataReader
DataReader  Odczyt strumienia danych zwróconych przez zapytanie
" Tylko do odczytu w przód
public interface IDataReader
" Szybki dostęp
{
" Praca w trybie połączeniowym
int Depth {get;}
" Programista zarządza połączeniem i danymi
bool IsClosed {get;}
" Małe zużycie zasobów
int RecordsAffected {get;}
&
void Close();
DataTable GetSchemaTable();
bool NextResult();
Użycie DataReader:
bool Read();
1. Stwórz i otwórz połączenie
&
2. Stwórz obiekt Command
}
3. Stwórz DataReader dla obiektu Command
4. Odczytaj dane
NextResult - Przejście do kolejnego zestawu wyników
5. Zamknij DataReader
6. Zamknij połączenie Read  Przechodzi do następnego rekordu
Użycie w bloku Try& Catch& Finally
Praca z IDataReader - przykład
" Stwórz obiekt i rozpocznij odczyt
IDataReader reader = cmd.ExecuteReader();
while (reader.Read()) {
" Przeczytaj kolumny do tablicy
object[ ] dataRow = new object[reader.FieldCount];
int cols = reader.GetValues(dataRow);
" Odczyt za pomocą indekserów
object val0 = reader[0];
object nameVal = reader["LastName"];
" Odczyt za pomocą metod
string firstName = reader.getString(2);
" Zamknięcie obiektu
}
reader.Close();
Odczyt danych z obiektu DataReader
// Open Connection and create command
" Wołanie Read dla każdego rekordu
SqlConnection conn = new
SqlConnection("data source=localhost;
 Zwraca false gdy brak danych
initial catalog=pubs; integrated
" Dostęp do pól
security=true");
 Dostęp poprzez indeks lub nazwę
SqlCommand cmdAuthors = new
 Funkcje Get& - najlepsza
SqlCommand("select * from Authors", conn);
wydajność
conn.Open();
while (myReader.Read())
// Create DataReader and read data
{
str += myReader[1];
SqlDataReader dr;
str += myReader["field"];
dr = cmdAuthors.ExecuteReader();
str += myReader.GetDateTime(2);
while (dr.Read())
}
{
lstBuiltNames.Items.Add(dr["au_lname"] + ",
" + dr["au_fname"]);
" Zamknięcie DataReader
}
" Zamkniecie połączenia
// Close DataReader and Connection
dr.Close();
conn.Close();
Transakcje
" Transakcje lokalne
 Dostęp z jednego połączenia
 Udostępnione przez ADO.NET
" Transakcje rozproszone
 Wykonywane na wielu połączniacj
 Użycie Microsoft Distributed Transaction Component
(MSDTC)
 namespace System.Transaction
Transkacje lokalne
<>
IDbCommand
" ADO.NET wspiera tranzakcyjność
...
 Transakcję rozpoczynamy poprzez metodę
IDbTransaction Transaction {get; set;}
BeginTransaction która zwraca obiekt
...
transakcji.
Transaction 1
 Transakcja wspiera metody wykonujące
<>
zmiany na bazie danych  polecenia
IDbTransaction
(Command)
//----- Properties
IDbConnection Connection {get;}
IsolationLevel IsolationLevel {get;}
" Transakcja jest
// Methods
 Zatwierdzana poprzez Commit
void Commit();
void Rollback();
 Wycofywana poprzez Rollback
...
Connection 1
<>
IDbConnection
&
IDbTransaction BeginTransaction();
IDbTransaction BeginTransaction
(IsolationLevel lvl);
1. Definicja
Transakcje - przykład
SqlConnection con = new SqlConnection(connStr);
IDbTranaction trans = null;
try {
con.Open();
trans = con.BeginTransaction(IsolationLevel.ReadCommitted);
2. Stworzenie obiektów
IDbCommand cmd1 = con.CreateCommand();
cmd1.CommandText = "DELETE [OrderDetails] WHERE OrderId = 10258";
cmd1.Transaction = trans;
cmd1.ExecuteNonQuery();
IDbCommand cmd2 = con.CreateCommand();
cmd2.CommandText = "DELETE Orders WHERE OrderId = 10258";
cmd2.Transaction = trans;
cmd2.ExecuteNonQuery();
3. Zatwierdzenie lub cofnięcie wyników
trans.Commit();
catch (Exception e) {
if (trans != null)
trans.Rollback();
}
finally {
try {
con.Close();
}
}
Poziomy izolacji
" Definiują blokady na odczyt i zapis
" ADO.NET zapewnia różne poziomy izolacji
public enum IsolationLevel {
ReadUncommitted, ReadCommitted, RepeatableRead, Serializable, ...
}
ReadUncommitted " Dostęp do zablokowanych danych
" Dirty reads
ReadCommitted " Odczyt zablokowanych wierszy zabroniony
" Brak dirty read, może wystąpić phantom row
" Non-repeatable reads
RepeatableRead " ReadCommitted bez non-repeatable reads
Serializable " Dostęp w seriach
" Najwyższy poziom izolacji
" Nie występują phantom rows
2.3.3 Tryb bezpołączeniowy: use DataSet
1
1. Klient tworzy żądanie wyświetlenia strony
Database
2. Tworzenie obiektów SqlConnection i SqlDataAdapter
2
3. Wypełnienie DataSet z DataAdapter i
Web server
3
SqlConnection
zamknięcie połączenia
4. Zwraca DataSet do klienta
4
SqlDataAdapter
5. Zmiana danych przez użytkownika
5
6. Aktualizacja danych DataSet
6
7. Użycie SqlDataAdapter do otwarcia
7
połączenia SqlConnection, aktualizacja
danych w bazie i zamknięcie połączenia
DataSet
List-Bound
Control
Client
Czym jest DataSet?
DataSet  baza danych utrzymywana w pamięci(struktuwa relacyjna)
" DataSet zawiera wiele
Tables
DataTables
" Relacje są reprezentowane
DataTable
DataView
poprzez DataRelation
DataRow(s)
" Można wymusić Constrainst
" Dostęp do danych w tabelach
DataColumn
Relations
poprzez DataRow i
DataColumn
Constraint(s)
DataViewManager
DataRelation
DataRelation
DataTable
DataTable
DataColumn
DataRow
DataTable
DataRelation
Stosowanie obiektu DataSet
" gdy dane muszą byd edytowane lub gdy do bazy trzeba dodawad
i usuwad rekordy.
" gdy zachodzi potrzeba organizowania danych - filtrowania, sortowania
czy wyszukiwania
" gdy rekordy pobrane z bazy danych będą przetwarzane w wielu
iteracjach
" gdy wynikowy zbiór danych pomiędzy kolejnymi odwołaniami do tej
samej strony musi zostad zachowany w obiekcie Session lub Cache.
" do przekazywania wyników działania obiektów warstwy biznesowej
i usług Web Service
 odłączony obiekt DataSet może byd serializowany do postaci XML i przesyłany z
wykorzystaniem protokołu HTTP
DataSet vs. DataReader
DataSet DataReader
Operacje odczytu i zapisu Tylko do odczytu
Wiele tabel z różnych zródeł Oparty o jedno polecenie SQL
Bezpołączeniowy Połączeniowy
yródło dla wielu kontrolek yródło dla jednej kontrolki
Przesuwanie się w przód i tył Przesuwanie tylko do przodu
Wolniejszy dostęp Szybszy dostęp
Wspierany przez narzędzia automatyzujące pracę Wymaga ręcznej implementacji
Diagram klasy DataSet
DataRelation
//----- Properties
DataSet
string RelationName {get; set;}
Relations
DataTable ParentTable {get;}
*
//----- Properties
DataColumn[] ParentColumns {get;}
string DataSetName {get; set;}
ParentRelations
DataTable ChildTable {get;}
DataRelationsCollection Relations {get;}
* DataColumn[] ChildColumns {get;}
DataTableCollection Tables {get;} ChildRelations
Transaction 1
...
PropertyCollection ExtendedProperties {get;}
*
string NameSpace {get;}
bool HasErrors {get;}
DataColumn
...
//----- Properties
*
bool AllowDBNull {get; set;}
ChildColumns
bool AutoIncrement {get; set;}
int AutoIncrementSeed {get; set;}
*
int AutoIncrementStep {get; set;}
Columns
* Tables
ParentColumns
string ColumnName {get; set;}
*
Type DataType {get; set;}
DataTable
string Expression {get; set;}
bool ReadOnly {get; set;}
bool Unique {get; set;}
//----- Properties
...
string TableName {get;}
DataRelationsCollection ChildRelations {get;}
DataRelationsCollection ParentRelations {get;}
ConstraintCollection Constraints {get;}
DataColumnCollection Columns {get;}
DataRow
DataView DefaultView {get;}
bool HasErrors {get;}
//----- Properties
DataColumn[] PrimaryKey{get; set;}
string DataSetName {get; set;}
DataRowCollection Rows {get;}
DataRelationsCollection Relations {get;}
...
DataTableCollection Tables {get;}
PropertyCollection ExtendedProperties {get;}
*
string NameSpace {get;}
Rows
bool HasErrors {get;}
...
Klasa DataSet
" DataSet składa się z Dostęp do:
 Kolecji DataTable
" DataTable
 Kolekcji DataRelation
 DataSet.Tables[0]
 DataSet.Tables* tablename +
" DataTable składa się z
" DataColumn
 collection of DataTableColumns
(= schema definition)
 DataTable.Columns[0]
 collection of DataTableRows
 DataTable.Columns* columnname +
(= data)
" DataRow
 DefaultView (DataTableView)
 DataTable.Rows[0]
" DataRelation
" Pola tabeli
 Aączy dwa obiekty DataTable
 DataRow[0]
 definiujue ParentTable i
 DataRow* columnname +
ParentColumns
oraz ChildTable i ChildColumns
Typowany i nietypowany DataSet
" Typowany dataset jest datasetem, który dziedziczony jest z bazowej klasy DataSet, a
następnie na podstawie informacji z bazy danych generuje nową klasę. Informacje o typach
(tabele, kolumny, relacje, & ) są dołączane do obiektu.
 VS daje możliwośd automatyczniej generacji typowanych datasetów
 Może zostad zbudowany w oparciu o dane z pliku XSD
 Mniej podatne na błędy
 Mniejsza elastycznośd
" Nietypowany dataset nie posiada wbudowanego schematu. Zawiera również tabele, wiersze,
kolumny, jednak są one udostępniane jako zwykłe kolekcje
 Rozwiązanie bardziej elastyczne, umożliwia pracę z nieznannym zródłem
" Porównanie:
 Poprawne dla obu typów:
MyDataSet.Tables[ News ].Rows[0][ Title ]
 Poprawne tylko dla typowanego DataSet + zwraca dane we właściwym formacie
MyDataSet.News[0].Title
Zdarzenia w DataTable
" Podział na trzy kategorie:
" Dla kolumn: ColumnChanging, ColumnChanged
 DataColumnChangeEventsArgs: Column, ProposedValue, Row
" Dla wierszy: RowChanging, RowChanged, RowDeleting,
RowDeleted
 DataRowChangeEventArgs: Action (Add, Change,
ChangeCurrentAndOriginal, ChangeOriginal, Commit, Delete,
Nothing, Rollback), Row
" Dla tabel: TableClearing, TableCleared, TableNewRow
 DataTableClearEventArgs: Table, TableName, TableNamespace
 DataTableNewRowEventArgs key member: Row
Wypełnianie DataSet: DataAdapter
DataAdapter służy jako most pomiędzy DataSetem a zródłem danych pozwalający
na wymianę danych. DataAdapter reprezentuje zestaw poleceń oraz połączenie
bazodanowe które są uzywane do wypełnia DataSet oraz aktualizacji bazy. Dane są
wymieniane poprzez zapytania SQL lub procedury składowane.
" DataAdapter - właściwości:
 SelectCommand  odczytuje dane ze zródła
 InsertCommand  zapisuje dane z DataSet do bazy
 UpdateCommand  aktualizuje dane w bazie danymi z DataSet
 DeleteCommand  usuwa dane z DataSer
" DataAdapter  metody:
 Fill  odświeża DataSet danymi z bazy (używa SELECT)
 Update  przenosi zmiany z DataSet do bazy (używa INSERT, UPDATE, DELETE)
DataAdapter - polecenia
" Tworzone w trzy sposoby
 Użycie obiektu CommandBuilder by stworzyd Command
podczas wykonania
" Proste do realizacji, narzut na wykonanie
" Ograniczenie do Select dla jednej tabeli
 Poprzez Visual Studio w trakcie tworzenia aplikacji
" Proste do realizacji, brak narzutu na wykonanie
" Ograniczenie do Select dla jednej tabeli
 Stworzenie programowo podczas tworzenia aplikacji
" Wysoka kontrola i wydajnośd
" Brak ograniczeo
" Narzut na czas implementacji
CommandBuilder
Obiekt CommandBuilder generuje polecenia wymagane do aktualizacji zródła
danych po wprowadzeniu zmian w obiekcie DataSet.
Ograniczenia:
" polecenie Select dotyczy pojedynczej tabeli
" tabela w bazie musi mieć klucz główny lub unikatową kolumnę zawartą w oryginalnym
poleceniu Select
DataTable dt= ds.Tables["movies"];
// Use command builder to generate update commands
SqlCommandBuilder sb = new SqlCommandBuilder(da);
// Add movie to table
DataRow drow = dt.NewRow();
drow["movie_Title"] = "Taxi Driver";
drow["movie_Year"] = "1976";
dt.Rows.Add(drow);
// Delete row from table
dt.Rows[4].Delete();
// Edit Column value
dt.Rows[5]["movie_Year"] = "1944";
// Update underlying Sql Server table
int updates = da.Update(ds, "movies");
MessageBox.Show("Rows Changed: " +updates.ToString());
Data Adapter - tworzenie
" Zapisanie zapytania w DataAdapter
SqlDataAdapter da = new SqlDataAdapter
("select * from Authors",conn);
" Konstruktor ustawia wartość SelectCommand
da.SelectCommand.CommandText;
da.SelectCommand.Connection;
" Gdy wymagane, utworzenie InsertCommand, UpdateCommand,
DeleteCommand
DataSet - tworzenie
" Aadowanie danych poprzez SelectCommand obiektu DataAdapter
 Definicja SQL, przez który zostaną załadowane dane
 SelectCommand jako konstruktor
private void Demo()
{
SqlDataAdapter da = new SqlDataAdapter(
"SELECT City FROM Authors",
"Server=localhost; Database=Pubs; Integrated Security=SSPI" );
DataSet ds = new DataSet();
da.Fill( ds, "Authors" ); // Opens and closes a connection
foreach ( DataRow dr in ds.Tables[ "Authors" ].Rows )
Console.WriteLine( dr[ "City" ] ); // Writes list of cities
}
DataSet - tworzenie
" Tworzenie i załadowanie danymi DataTable
 Fill wywołuje SelectCommand obiektu DataAdapter
DataSet ds = new DataSet();
da.Fill(ds, "Authors");
" Dostęp do DataTable
ds.Tables["Authors"].Rows.Count;
string str="";
foreach(DataRow r in
ds.Tables["Authors"].Rows)
{
str += r[2];
str += r["au_lname"];
}
Wypełnianie DataSet
Wydajność
" Zdefiniowanie schematu przed wypełnieniem DataSet
 DataTables, DataColumns, DataRelations są znane przed załadowaniem danych
 Zwiększenie wydajności
" Tworzenie typowanych DataSet:
- dsCustomers.Customers.BeginLoadData();
- daCustomers.Fill(dsCustomers.Customers);
- dsCustomers.Customers.EndLoadData();
- dataGrid1.DataSource = dsCustomers.Customers.DefaultView;;
Dane z wielu DataAdapter
" DataSet może przechowywać dane z wielu obiektów DataAdapter
 1 DataAdapter = 1 DataTable
" Wywołanie metody Fill
 Określenie tabeli
- daCustomers.Fill(dsCustomerOrders.Customers);
- daOrders.Fill(dsCustomerOrders.Orders);
- dataGrid1.DataSource = dsCustomerOrders.Customers.DefaultView;
DataSet - podsumowanie
" DataSet może:
 Przechowywad dane w wielu powiązanych tabelach
 Modelowad zależności między tabelami
 Zarządza constrainami
 Daje dostęp do widoków celem bardziej efektywnego
wyświetlania danych
 Byd przesyłany pomiędzy procesami i warstwami
" DataSet i XML:
 XML może zostad załadowany do DataSet
 DataSet może zostad przesłany jako XML
 DataSet może wczytywad xsd
DataView
" DataView służy modyfikowaniu DataTable celem wyświetlenia potrzebych
danych
" DefaultView zwraca standardowy widok dla DataTable
DataView dv = ds.Tables["Authors"].DefaultView;
" Modyfikacja widoku z DataSet poprzez filtry
DataView dv = new DataView(ds.Tables["Authors"]);
dv.RowFilter = "state = 'CA'";
Trzy parametry opcjonalne
" Filter, "City='London'"
" Sort, "CompanyName ASC"
" DataViewRowState
Relacje
" Kolumna rodzica
DataColumn parentCol = ds.Tables["Customers"].Columns["CustomerID"]
" Kolumna dziecka
childCol = ds.Tables["Orders"].Columns["CustomerID"]
" Stworzenie relacji
parentCol DataRelation
Customers table
dr = New DataRelation _
( CustOrders", parentCol, _
childCol)
childCol
ds.DataRelations.Add(dr)
Orders table
DataSet
DataRelation definiuje relację na potrzeby nawigacji
Nawigacja poprzez relacje
ds.Tables[index].Rows[index].GetChildRows("relation");
ds.Tables[index].Rows[index].GetParentRow("relation");
Orders
Customers
GetChildRows
GetParentRow
DataSet
DataView tableView;
DataRowView currentRowView;
tableView = new DataView(ds.Tables["Customers"]);
currentRowView = tableView[dgCustomers.SelectedIndex];
dgChild.DataSource = currentRowView.CreateChildView("CustOrders");
Customers Orders
DataRowView
DataView
CreateChildView
DataSet
Modyfikacja danych w DataTable
" BeginEdit rozpoczyna edycję danych
DataRos drEmployee =
" EndEdit i CancelEdit kończą edycję danych
dtEmployees.Rows(3)
drEmployee.BeginEdit()
drEmployee("FirstName") = "John"
drEmployee("LastName") = "Smith"
Wstawianie wiersza
drEmployee.EndEdit()
" Stworzenie wiersza
DataRow drNewEmployee = dtEmployees.NewRow()
" Wypełnienie danymi
drNewEmployee("EmployeeID") = 11
drNewEmployee("LastName") = "Smith"
" Dodanie do DataTable
dtEmployees.Rows.Add(drNewEmployee)
" Jednowierszowo
dtEmployees.Rows.Add( New Object() {11, "Smith"})
Modyfikacja danych w DataTable
Usuwanie wiersza
" Metoda Remove
 Usuwa wiersz z kolekcji
 Przykład:
dtEmployees.Rows.Remove(drEmployee)
" Metoda Delete klasy DataRow
 Oznacza wiersz jako usunięty
 Wiersz staje się  ukryty , możemy uzyskać do niego dostęp
 Przykład:
drEmployee.Delete()
Śledzenie zmian w DataSet
" DataRow może przechowywad wiele wersji wiersza:
 DataRowVersion.Current
" Aktualna wartośd
 DataRowVersion.Original
" Wartośd przed dokonaniem zmian
 DataRowVersion.Proposed
" Wartośd w trakcie cyklu BeginEdit / EndEdit
 DataRowVersion.Default
" Wartośd standardowa
RowVersion - stany
CURRENT ORIGINAL PROPOSED
White White N/A
dataRow.BeginEdit();
dataRow[ "au_lname" ]
= "Brown";
White White Brown
dataRow.EndEdit();
Brown White N/A
dataRow[ "au_lname", DataRowVersion.Current ] // Brown
dataRow[ "au_lname", DataRowVersion.Original ] // White
Diagram stanów obiektu DataRow
" DataRow może być w różnych stanach
public DataRowState RowState {get;}
public enum DataRowState {
Added, Deleted, Detached, Modified, Unchanged
}
row =table.NewRow
Detached
table.Rows.
Remove(row)
row[..] = ..
table.Row.
Reject-
Add(row)
Changes
row.
Reject-
Delete
Changes
Accept-
Added Unchanged Modified
Changes
Accept-
Changes
Accept-
Changes
RejectChanges
Deleted
row.Delete
row.Delete
Modyfikacja zródła danych
" Modyfikacja zródła danych przez DataAdapter
 InsertCommand, UpdateCommand, DeleteCommand
" Modyfikacje są zapisywane poprzez metodę Update obiektu DataAdapter
 DataAdapter przeszukuje wiersze pod kątem RowState
 Wykonuje akcję zgodnie ze stanem wiersza
DataRows in DataTable
RowState = Modified Use UPDATE command
RowState = Unchanged
Ignore
RowState = Added Use INSERT command
Use UPDATE command
RowState = Modified
RowState = Deleted Use DELETE command
Optymalizacja zmian
" DataSet oraz DataTable wspierają metodę
GetChanges
 GetChanges bez argumentów
" Pobiera wiersze, których RowState jest inny niż Unchanged
" Wykorzystanie podczas przekazywania między warstwami
dsChanges = ds.GetChanges();
 GetChanges z argumentem RowState
" Wiersze, które mają określony RowState
" Pozwala zarządzad kolejnością aktualizacji
changes = ds.GetChanges( DataRowState.Added );
" Medota Merge pozwala na scalenie danych
Obsługa współbieżnego dostępu do danych
" Tryb bezpołączeniowy używa podejścia optymistycznego (optimistic
concurrency)
 Zwalnianie blokad podczas rozłączania
" Możliwość konfliktów
 Dane mogły zostać zmienione
- Usunięcie wiersza
- Zmiana wartości w polu wiersza
Wykrywanie konfliktów
" Data Adapter Configuration Wizard pozwala generować zapytania SQL
wykrywające konflikty
" Podczas aktualizacji:
 Porównanie bieżących wartości z oryginalnymi (where & )
 Różnice powodują konflikt
" Dodanie do tabeli pola timestamp - aktualizacja pola przy zmianie wartości.
http://msdn.microsoft.com/en-us/library/aa0416cz.aspx
http://msdn.microsoft.com/msdnmag/issues/04/09/DataPoints
Naruszenie spójności danych
User1 czyta wiersz
Column name Original value Current value Value in database
CustID 101 101 101
LastName Smith Smith Smith
FirstName Bob Bob Bob
User2 zmienia FirstName z "Bob" na "Robert" i zapisuje zmiany
Column name Original value Current value Value in database
CustID 101 101 101
LastName Smith Smith Smith
FirstName Bob Robert Bob
User1 zmienia FirstName na "James i próbuje aktualizować bazę
Column name Original value Current value Value in database
CustID 101 101 101
LastName Smith Smith Smith
FirstName Bob James Robert
Wykrywanie konfliktów
// Visual C#: How the Data Adapter Configuration Wizard Supports Optimistic Concurrency
this.cmUpdate.CommandText =
"UPDATE Customers " +
"SET CustomerID=@CustomerID, CompanyName=@CompanyName " +
" WHERE (CustomerID = @Original_CustomerID) " +
" AND (CompanyName = @Original_CompanyName); " +
"SELECT CustomerID, CompanyName FROM Customers " +
" WHERE (CustomerID = @CustomerID)";
this.cmUpdate.Parameters.Add(new SqlParameter(
"@CustomerID", SqlDbType.NChar, 5, ParameterDirection.Input, false, 0, 0, "CustomerID",
DataRowVersion.Current, null));
this.cmUpdate.Parameters.Add(new SqlParameter( "@CompanyName", SqlDbType.NVarChar, 40,
ParameterDirection.Input, false, 0, 0, "CompanyName", DataRowVersion.Current, null));
this.cmUpdate.Parameters.Add(new SqlParameter( "@Original_CustomerID", SqlDbType.NChar, 5,
ParameterDirection.Input, false, 0, 0 , "CustomerID", DataRowVersion.Original, null));
this.cmUpdate.Parameters.Add(new SqlParameter( "@Original_CompanyName",
SqlDbType.NVarChar, 40, ParameterDirection.Input, false, 0, 0, "CompanyName",
DataRowVersion.Original, null));
this.cmUpdate.Parameters.Add(new SqlParameter( "@CustomerID",
SqlDbType.NChar, 5, ParameterDirection.Input, false, 0, 0, "CustomerID", DataRowVersion.Current,
null));
Rozwiązywanie konfliktów
" Właściwość HasErrors
 Sprawdza DataSet, DataTable, DataRow
" Jedna ze strategii:
  Last in wins  zmiany są zapisywane niezależnie od stanu
 Zatrzymanie wartości w DataSet i aktualizacja pózniej
 Odrzut konfliktów i wypełnienie ich danymi z DataSet
 Odrzut konfliktów i wypełnienie ich danymi z bazy
Kontrolki zródła danych
ObjectDataSource Umożliwia połączenie z obiektami logiki biznesowej i innych klas i służy do tworzenia aplikacji
webowych które bazują na obiektach warstwy pośredniej do zarządzania danymi. Wspiera
zaawansowane sortowania i dzielenie na strony niedostępne w innych kontrolkach zródeł
danych.
Umożliwia połączenie do serwerów baz danych takich jak Microsoft SQL Server czy Oracle.
SqlDataSource
We współpracy z serwerem SQL Server wspiera zaawansowane możliwości buforowania.
Kontrolka wspiera również sortowanie, filtrowanie i dzielenie na strony, jeśli dane są zwracane
jako obiekt DataSet.
Umożliwia współpracę z bazami danych zapisanymi w Microsoft Access. Kontrolka wspiera
AccessDataSource
sortowanie, filtrowanie i dzielenie na strony, jeśli dane są zwracane jako obiekt DataSet
Umożliwia pobieranie danych zapisanych w plikach XML, szczególnie dla hierarchicznych
XmlDataSource
kontrolek serwerowych ASP.NET takich jak TreeView. Wspiera filtrowanie przy użyciu wyrażeo
XPath i umożliwia stosowanie transformacji danych przy użyciu XSLT. Umożliwia również
aktualizację danych przez zapisanie całego dokumentu XML ze zmianami.
Używana w ASP.NET do nawigacji na stronie
SiteMapDataSource
Umożliwia użycie języka LINQ na stronach ASP.NET poprzez model deklaratywny do pobrania
LinqDataSource
i modyfikowania danych z obiektów danych takich jak tabele w bazie czy kolekcje w pamięci
serwera. Wspiera automatyczne generowanie poleceń wybierania, aktualizacji, dodawania i
usuwania danych. Kontrolka wspiera sortowanie, filtrowanie i dzielenie na strony
Umożliwia połączenie z danymi pochodzącymi z modelu Entity Data Model (EDM). Wspiera
EntityDataSource
automatyczne generowanie poleceń wybierania, aktualizacji, dodawania i usuwania danych.
Kontrolka wspiera sortowanie, filtrowanie i dzielenie na strony.
Połączenie i tworzenie zapytao przy pomocy SqlDataSource
Określić atrybuty kontrolki SqlDataSource:
" ConnectionString  łańcuch połączenia.
" ProviderName  nazwa dostawcy danych.
" SelectCommand  polecenie SQL zawierające treść zapytania do bazy danych lub
nazwa procedury składowanej do wykonania.
ConnectionString="Data Source=.\SQLEXPRESS; AttachDbFilename=|DataDirectory|\CDDB.mdf;
Integrated Security=True; User Instance=True"
ProviderName="System.Data.SqlClient"
SelectCommand="SELECT * FROM [Kategorie]">

lub
ConnectionString="<%$ ConnectionStrings:PolaczenieDoBazy %>"
SelectCommand="SELECT * FROM [Kategorie]">
W bloku pliku Web.config


providerName="System.Data.SqlClient" />

Połączenie i tworzenie zapytao przy pomocy SqlDataSource
" Konfiguracja treści zapytania do bazy
ConnectionString="<%$ ConnectionStrings:PolaczenieDoBazy %>"
SelectCommand="SELECT * FROM [Kategorie]"
DeleteCommand="DELETE FROM [Kategorie] WHERE [KatID] = @KatID"
InsertCommand="INSERT INTO [Kategorie] ([Nazwa]) VALUES (@Nazwa)"
UpdateCommand="UPDATE [Kategorie] SET [Nazwa] = @Nazwa WHERE [KatID] = @KatID">











XML i Dataset
WriteXML
XML File XML File
DataAdapter
Doc.Save
DataSet XmlDataDocument
Database
Object Object
XslTransform
Object
ReadXML
XML File
XML or
XSLT File
HTML File
Dlaczego używad XML z Dataset
" XML to uniwersalny format wymiany danych między klientami
" Synchronizacja i transformacja danych
Firewall
Human Readable
Web Server
XML File
Browser Readable
Or Stream
DataSet
Mainframe Readable
 Typowane DataSet generowane z XML schema
" Silna integracja
 Dostęp do DataSet poprzez interfejs XML-DOM
 serializacjaDataSet do XML
" Integracja w systemach rozproszon
 XML jako zródło danych dla DataSet
 Schema dla DataSets zdefiniowana jako XML
schemas
Metody klasy DataSet do obsługi danych i schematów XML
" ReadXML  Aadowanie XML
" WriteXml - zapis DataSet do strumienia XML
" WriteXmlSchema  wygenerowanie schemy z DataSet
" ReadXmlSchema  załadowanie XML Schema
" InferXmlSchema  stworzenie schemy DataSet na podstawie
XML
" GetXml i GetXmlSchema  zwraca ciąg XML lub XML Schema
Metody klasy DataSet do obsługi danych i
schematów XML
" Use ReadXml to load data from a file or stream
DataSet ds = new DataSet();
ds.ReadXml(Server.MapPath("filename.xml"));
" Use WriteXml to write XML data to a file or stream
DataSet ds = new DataSet();
SqlDataAdapter da = new SqlDataAdapter("select * from
Authors", conn);
da.Fill(ds);
ds.WriteXml(Server.MapPath("filename.xml"));
" Use GetXml to write data to a string variable
string strXmlDS = ds.GetXml();
Synchronizacja DataSet z XmlDataDocument
" Załadowanie XML Data do XmlDataDocument
XmlDataDocument objXmlDataDoc = new XmlDataDocument();
objXmlDataDoc.Load(Server.MapPath ("file.xml"));
" Załadowanie DataSet do XmlDataDocument
DataSet ds = new DataSet();
//fill in ds
objXmlDataDoc = new XmlDataDocument(ds);
Praca z XmlDataDocument
" Załadowanie danych
dg.DataSource = objXmlDataDoc.DataSet;
" Pobranie wierszy jako XML
XmlElement elem;
elem = objXmlDataDoc.GetElementFromRow(ds.Tables[0].Rows[1]);
" Metody XML DOM
 XmlDataDocument dziedziczy z XmlDocument


Wyszukiwarka

Podobne podstrony:
ASP NET Module 3 Using Microsoft ADO NET to Access Data
@PSI W14b Platforma NET ADO LINQ
Debugowanie NET Zaawansowane techniki diagnostyczne?bnet
CSharp Introduction to C# Programming for the Microsoft NET Platform (Prerelease)
aoki densetsu shoot! e05 [saizen] (osloskop net)
net h (2)
DOD Net Centric Data Strategy and Community of Interest (COI) Training Glossary
Klass 2007 DVDRip XviD MESS (osloskop net)
net 3 howto pl 8
java net URLStreamHandler
VB NET Module 1 Overview of the Microsoft NET Platform
java net UnknownServiceException

więcej podobnych podstron