background image

Zastosowanie 
zaawansowanych technik 
obsługi danych 

Bardzo szybko poznawałeś róŜne metody dostępu do danych. Teraz, kiedy juŜ opanowałeś 
podstawy, nadszedł czas aby przejść na kolejny, bardziej zaawansowany poziom. W tym rozdziale 
skoncentrujemy się na technikach bardziej zaawansowanych w porównaniu z tymi, 
przedstawionymi w poprzednich częściach niniejszej ksiąŜki. Poznasz w nim nowe bazy danych 
oraz nowe metody operowania na danych XML, które umoŜliwią Ci tworzenie profesjonalnych 
aplikacji internetowych. 

W pierwszej kolejności przyjrzymy się metodom pobierania informacji przy uŜyciu parametrów i 
procedur zachowanych. Parametry pozwalają na tworzenie zapytań w sposób bardziej efektywny. 
Procedury zachowane są natomiast przygotowywanymi wcześniej poleceniami SQL, których 
wykorzystanie przynosi wiele korzyści, do których naleŜy zaliczyć zwiększenie szybkości 
działania aplikacji oraz poprawienie jej przejrzystości. Dowiesz się takŜe, w jaki sposób, poprzez 
wykorzystanie transakcji, moŜna zapewnić, Ŝe polecenia SQL będą wykonywane poprawnie. 

W drugiej części tego rozdziału znajdziesz dodatkowe informacje na temat języka XML. Poznasz 
klasę 

XmlNavigator

, której moŜna uŜywać podobnie  jak klasy 

XmlDocument

. Wykorzystując 

obiekty tej klasy, moŜna zadawać pytania XPath oraz wykonywać przekształcenia XSL. XPath to 
języka zapytań stosowany wraz z językiem XML, natomiast XSL to język pozwalający na 
przekształcanie plików XML do postaci wszelkich innych dokumentów strukturalnych, takich jak 
na przykład dokumenty HTML. Aby stać się ekspertem w dziedzinie ASP.NET koniecznie naleŜy 
poznać wiele róŜnych sposobów umoŜliwiających uzyskanie tego samego rezultatu. Po 
przeczytaniu tego rozdziału będziesz juŜ znał kilka róŜnych sposobów pobierania informacji z baz 
danych oraz plików XML. 

W tym rozdziale omówione zostaną następujące zagadnienia: 

 

Czym są zapytania parametryzowane oraz jak naleŜy je stosować. 

 

Czym są procedury zachowane oraz jak naleŜy je stosować. 

 

Jak wykorzystywać transakcje. 

 

Jakie są inne sposoby odczytywania zawartości dokumentów XML. 

 

Sposoby przeszukiwania plików XML. 

 

Sposoby przekształcania plików XML. 

background image

Zaawansowane techniki obsługi baz danych 

Jak na razie wszelkie operacje związane z wykorzystaniem baz danych były wykonywane przy 
uŜyciu obiektów 

OleDbDataAdapter

OleDbCommand

DataSet

 oraz kilku innych. Dostarczają 

one wszelkich moŜliwości funkcjonalnych potrzebnych przy tworzeniu aplikacji ASP.NET. 
Jednak nie poznałeś jeszcze wszystkich moŜliwości jakie obiekty te dają, w szczególności chodzi 
tu o parametry, procedury zachowane oraz transakcje. 

Parametry są nowym sposobem tworzenia dynamicznych poleceń SQL. OtóŜ zamiast tworzyć 
pytanie SQL składając je z fragmentów pochodzących z wielu róŜnych źródeł, moŜna wykorzystać 
parametry, które poinformują bazę danych jakie informacje naleŜy zwrócić. Takie rozwiązanie jest 
nie tylko prostsze, lecz takŜe bardziej eleganckie. Procedury zachowane są natomiast 
przygotowywanymi wcześniej poleceniami SQL, które mogą poprawić efektywność działania 
aplikacji. Wykorzystanie procedur zachowanych wraz z parametrami stanowi doskonały sposób 
przeszukiwania i pobierania informacji z baz danych. Transakcje pozwalają natomiast na 
zapewnienie integralności i poprawności informacji poprzez wykonywanie operacji na bazach 
danych zgodnie z paradygmatem „wszystko albo nic”. Oznacza to, Ŝe zostaną wprowadzone 
wszystkie modyfikacje lub nie zostanie wprowadzona Ŝadna z nich. Poznasz takŜe kilka 
najczęstszych sytuacji, w których są wykorzystywane transakcje. 

Dzięki tym zaawansowanym technikom obsługi baz danych będziesz w stanie tworzyć aplikacje o 
znacznie większych moŜliwościach, a jednocześnie poprawić efektywność ich działania. 

Zapytania sparametryzowane 

Wyobraź sobie proces budowy domu. Konieczna jest przy tym szczegółowa znajomość wymiarów 
elementów konstrukcyjnych oraz miejsc, w których naleŜy ich uŜyć. Jednym ze sposobów 
realizacji tego zagadnienia byłoby zebranie wszystkich elementów i zapisanie wszystkich 
informacji bezpośrednio na nich. Na wszystkich panelach podłogowych, oknach, ościeŜnicach, 
rurach i wszelkich innych elementach, zostałyby zapisane wymiary oraz docelowe połoŜenie. Taka 
metoda mogłaby spełnić swoje zadanie, lecz jednocześnie jest bardzo niedokładna i moŜe stać się 
przyczyną wielu problemów. Zamiast niej, moŜna jednak wykorzystać plan — kartkę papieru, 
która informuje gdzie mają być umieszczone poszczególne elementy i jak je naleŜy połączyć. 

Podobnie rzecz się ma z dostępem do danych. Gdy tworzone jest polecenie SQL, moŜna zebrać 
poszczególne jego elementy i połączyć je ze sobą w jeden łańcuch znaków, zapisując jednocześnie 
informacje o tym za co odpowiadają jego poszczególne części. MoŜna jednak wykorzystać 
bardziej zorganizowaną metodę określenia, gdzie naleŜy umieścić poszczególne informacje. Ta 
druga metoda wykorzystuje 

parametry

 — fragmenty informacji tworzone niezaleŜnie od polecenia 

SQL i uŜywane w nim. Bazy danych posługują się parametrami w taki sam sposób, w jaki 
budowniczy korzystają z planów. 

Parametry wykorzystywane są w raz z obiektami 

OleDbCommand

 w celu podania dodatkowych 

informacji, takich jak dane, które naleŜy zwrócić lub sposób ich zapisania w obiekcie 

DataSet

Przypomnij sobie informacje dotyczące poleceń SQL podane w rozdziale 10, pt.: „Korzystanie z 
baz danych za pomocą obiektów ADO.NET”. Aby dynamicznie stworzyć zapytanie, 
niejednokrotnie trzeba pobierać informacje z róŜnych elementów kontrolnych wykorzystywanych 
na stronach ASP.NET. Przykładowo, wyobraź sobie następujące zapytanie: 

strSQL = "select * from tblUsers where UserID = 1" 
 

Wartość 

UserID

 mogłaby pochodzić z pola tekstowego wyświetlonego na stronie. A zatem, 

moŜna by stworzyć zapytanie w następujący sposób (zakładając, Ŝe 

tbId

 jest nazwą pola 

tekstowego): 

strSQL = "select * from tblUsers where UserID = " & tbId.Text 
 

PowyŜsza metoda spełnia swoje zadanie jeśli chodzi o zapewnienie moŜliwości dynamicznego 
stworzenia zapytania SQL, jednak nie jest „zorganizowana”. Co by się bowiem stało gdyby na 
stronie były inne pola tekstowe? Wtedy mogłyby się pojawić problemy z określeniem, które z pól 
powinno zawierać jakie informacje; największe problemy mieliby inni programiści próbujący 
przeanalizować kod strony. 

background image

Nowe określenie

 

Jednak bardziej efektywną metodą jest uŜycie parametrów. 

Parametr

 jest wartością przekazywaną 

do, bądź zwracaną przez zapytanie. Wykorzystanie parametrów pozwala na zachowanie 
przejrzystości informacji i ułatwia analizę stosowanych zapytań. Zastąpmy zatem poprzednie 
zapytanie, zapytaniem sparametryzowanym: 

strSQL = "select * from tblUsers where UserID = @ID" 
 

Jak widać dynamicznie tworzona część łańcucha znaków została zastąpiona parametrem 
zapytania, oznaczonym przy uŜyciu symbolu 

@

. ZauwaŜ, iŜ parametr ten stanowi część zapytania 

SQL. Teraz, w jakimś miejscu, naleŜy podać wartość tego parametru. Wartości parametrów 
określane są przy uŜyciu kolekcji 

Parameters

 obiektu 

OleDbCommand

 (więcej informacji na 

jego temat znajdziesz w rozdziale 10). Przykład wykorzystania sparametryzowanych zapytań SQL 
przedstawiłem na listingu 12.1. 

 

Listing 12.1. 

Określanie wartości parametrów zapytania SQL — fragment kodu 

1

 

dim objCmd as OleDbCommand = new OleDbCommand _ 

2

 

  ("select * from tblUsers where UserID = @ID", Conn) 

3

 

   

4

 

dim objParam as OleDbParameter 

5

 

objParam = objCmd.Parameters.Add("@ID", OleDbType.Integer) 

6

 

objParam.Direction = ParameterDirection.Input 

7

 

objParam.Value = tbId.Text 

 

Analiza 

W wierszach 1. oraz 2., w normalny sposób jest tworzony obiekt 

OleDbCommand

 (zakładam przy 

tym, Ŝe został juŜ utworzony obiekt 

OleDbConnection

 o nazwie 

Conn

). Warto zwrócić uwagę na 

wiersz 2., w którym tworzone jest zapytanie sparametryzowane. W wierszu 4. tworzony jest obiekt 

OleDbCommand

, który zostanie wykorzystany do przekazania wartości parametru do zapytania 

SQL. W wierszu 5. parametr uŜyty w zapytaniu jest dodawany do obiektu 

OleDbCommand

, a 

jednocześnie określana jest jego nazwa i typ. Nazwa parametry podana w wywołaniu metody 

Add

 

musi odpowiadać parametrowi uŜytemu w zapytaniu SQL (w tym przypadku musi ona mieć 
postać 

@ID

). Typ jest wartością 

OleDbType

 i reprezentuje typ przekazywanej wartości parametru. 

Najczęściej stosowane wartości typów przedstawione zostały w tabeli 12.1. 

 

Tabela 12.1. 

Najczęściej stosowane wartości 

OleDbType

 

Typ 

Opis 

Binary 

Strumień bajtów (odpowiada tablicy bajtów) 

Boolean 

Wartość logiczna 

BSTR 

Łańcuch znaków (odpowiada wartości typu 

String

Char 

Łańcuch znaków (odpowiada wartości typu 

String

Currency 

Wartość monetarna (odpowiada wartości typu 

Decimal

Date 

Data (odpowiada wartości typu 

DateTime

Decimal 

Wartość typu 

Decimal

 

Double 

Wartość typu 

Double

 

Empty 

Brak wartości 

Error 

32-bitowy kod błędu (odpowiada wartości typu 

Exception

Integer 

32-bitowa liczba całkowita (odpowiada wartości typu 

Integer

LongVarChar 

Długi łańcuch znaków (odpowiada wartości typu 

String

background image

VarChar 

Łańcuch znaków (odpowiada wartości typu 

String

Variant 

Specjalny typ danych, który moŜe reprezentować dane dowolnego typu, jeśli 
Ŝ

aden typ nie został określony (odpowiada wartości typu 

Object

 

W wierszu 6. określany jest rodzaj parametru

1

. W tym przypadku parametr będzie 

wykorzystywany jako element zapytania 

SELECT

, a zatem jego wartość będzie przekazywana 

do

 

zapytania. Stąd teŜ, właściwości określającej rodzaj zostanie przypisana wartość 

Input

. Gdyby 

wartość była zwracana i zapisywana w parametrze, to jego rodzaj naleŜałoby określić jako 

Output

. Więcej informacji na temat kierunków przekazywania informacji przez parametry podam 

w dalszej części rozdziału, poświęconej procedurom zachowanym. 

W końcu, w wierszu 7., określana jest wartość parametru; w tym przypadku zostaje jej przypisana 
zawartość pola tekstowego 

tbId

. Dowolne informacje podane w tym polu tekstowym zostaną 

zatem przekazane jako parametr do zapytania 

select

. Przeanalizuj teraz pełny kod przykładu, 

podany na listingu 12.2. 

 

Listing 12.2. 

Wykorzystanie parametrów do pobierania informacji z baz danych 

1

 

<%@ Page Language="VB" %> 

2

 

<%@ Import Namespace="System.Data" %> 

3

 

<%@ Import Namespace="System.Data.OleDb" %> 

4

 

 

5

 

<script runat="server"> 

6

 

   dim Conn as new OleDbConnection("Provider=" & _ 

7

 

            "Microsoft.Jet.OLEDB.4.0;" & _  

8

 

            "Data Source=C:\ASPNET\Data\banking.mdb") 

9

 

    

10

 

   sub GetData(obj as Object, e as EventArgs) 

11

 

      dim objCmd as OleDbCommand = new OleDbCommand _ 

12

 

        ("select * from tblUsers where UserID = @ID", Conn) 

13

 

      dim objReader as OleDbDataReader 

14

 

      dim objParam as OleDbParameter 

15

 

       

16

 

      objParam = objCmd.Parameters.Add("@ID", _  

17

 

        OleDbType.Integer) 

18

 

      objParam.Direction = ParameterDirection.Input 

19

 

      objParam.Value = tbId.Text 

20

 

       

21

 

      try  

22

 

        objCmd.Connection.Open() 

23

 

        objReader = objCmd.ExecuteReader 

24

 

      catch ex as OleDbException 

25

 

        Label1.Text = "Bł

ą

d pobierania informacji z bazy danych." 

26

 

      end try 

27

 

 

28

 

      DataGrid1.DataSource = objReader 

29

 

      DataGrid1.DataBind() 

30

 

       

31

 

      objReader.Close 

32

 

      objCmd.Connection.Close() 

33

 

   end sub 

34

 

</script> 

35

 

 

36

 

<html><body> 

37

 

   <form runat="server"> 

38

 

      <asp:Label id="Label1" runat="server" /><br> 

39

 

      Podaj ID: <asp:TextBox id="tbID" runat="server" 

40

 

          AutoPostBack=True 

41

 

          OnTextChanged=GetData /><p> 

42

 

      <asp:DataGrid id="DataGrid1" runat="server"  

43

 

         BorderColor="black" GridLines="Vertical"  

44

 

         cellpadding="4"     cellspacing="0"  width="100%" 

45

 

         Font-Name="Arial"   Font-Size="8pt"  

46

 

         HeaderStyle-BackColor="#cccc99" 

                                                           

1

 Rodzaj parametru nazywany jest takŜe „kierunkiem”, gdyŜ określa on kierunek w jakim parametr będzie 

przekazywał informacje. 

background image

47

 

         ItemStyle-BackColor="#ffffff" 

48

 

         AlternatingItemStyle-Backcolor="#cccccc"  

49

 

         AutoGenerateColumns="true" /> 

50

 

   </form> 

51

 

</body></html> 

 

Analiza 

Kod przedstawiony na powyŜszym listingu powinien wyglądać znajomo — jest on bowiem bardzo 
podobny do przykładów wykorzystania informacji pobieranych z baz danych, przedstawionych w 
rozdziale 10. W części przykładu zawierającej kod HTML stworzone zostały trzy elementy 
sterujące obsługiwane na serwerze: 

DataGrid

 (zdefiniowany w wierszach od 42. do 49.), 

Label

 

(zdefiniowany w wierszu 39.) oraz 

TextBox

 (zdefiniowany w wierszach od 39. do 41.). Gdy 

uŜytkownik wpisze jakąś wartość w polu tekstowym, zostanie zgłoszone zdarzenie 

TextChanged

w wyniku jego obsługi, w elemencie sterującym 

DataGrid

 zostaną wyświetlone odpowiednio 

przefiltrowane informacje (zwróć uwagę na atrybut 

AutoPostBack=True

 umieszczony w 

wierszu 40.). W wierszu 6. deklarowany jest obiekt 

OleDbConnection

, który będzie 

wykorzystywany w procedurze 

GetData

Procedura 

GetData

 jest wykonywana w celu obsługi zdarzenia 

TextChanged

 generowanego 

przez pole tekstowe i słuŜy do wyświetlenia odpowiednich informacji. Nasze sparametryzowane 
zapytanie jest tworzone w wierszach 11. i 12. W wierszach do 16. do 19. tworzony jest parametr, 
określany kierunek przekazywania informacji oraz jego wartość (wyznaczana na podstawie 
wartości właściwości 

Text

 pola tekstowego 

tbID

). Pozostała część procedury pobiera dane i 

wiąŜe je z elementem sterującym 

DataGrid

. Na rysunku 12.1 przedstawione zostały wyniki 

wygenerowane przez powyŜszy przykład, po wpisaniu jakiejś wartości w polu tekstowym. 

 

 

Rysunek 12.1. 

Sparametryzowane zapytanie wykorzystujące zawartość pola tekstowego w celu 

określenia informacji jakie naleŜy wyświetlić 

 

W jednym zapytaniu moŜna uŜyć wielu róŜnych parametrów. Na przykład: 

strSQL = "SELECT * FROM tblUsers WHERE UserID=@ID AND FirstName=@Name" 
 

W parametrze moŜna takŜe umieścić wartość zwracaną przez zapytanie: 

strSQL = "SELECT @Phone=Phone FROM tblUsers WHERE UserID=@ID 
          AND FirstName=@Name" 
 

Parametry zwracające informacje określane są jako 

parametry wyjściowe

. W efekcie wykonania 

powyŜszego zapytania (

SELECT Phone FROM tblUsers WHERE UserID=@ID AND 

FirstName=@Name

) zwrócona przez nie wartość zostanie zapisana w parametrze 

@Phone

. Po 

wykonaniu tego zapytania, wartość parametru będzie moŜna pobrać z kolekcji parametrów. 

background image

Przedstawiony poniŜej fragment kodu tworzy parametr wyjściowy dla ostatniego, 
przedstawionego wcześniej zapytania SQL: 

dim objParam as OleDbParameter 
objParam = objCmd.Parameters.Add("@Phone", OleDbType.BSTR) 
objParam.Direction = ParameterDirection.Output 
 

Wartość tego parametru moŜna pobrać po wykonaniu zapytania, przy wykorzystaniu właściwości 

Value

dim strPhone as string = objParam.Value 
 

Parametry są niezwykle przydatne przy tworzeniu dynamicznych zapytań, jednak ich prawdziwe 
moŜliwości uwidaczniają się dopiero przy zastosowaniu wraz z procedurami zachowanymi. 

Procedury zachowane 

Procedura zachowana jest zbiorem poleceń (zazwyczaj poleceń SQL połączonych z instrukcjami 
zapisanymi w innym języku, charakterystycznym dla uŜywanej bazy danych), które baza danych 
jest w stanie wykonać. Jaka jest róŜnica pomiędzy procedurą zachowaną a zwyczajnymi 
poleceniami SQL? 

Po pierwsze procedury zachowane są kompilowane. JuŜ wiesz jakie korzyści daje kompilowanie 
stron ASP.NET. Bardzo podobne korzyści daje kompilacja procedur zachowanych; dotyczy to 
takŜe zwiększenia szybkości ich działania. 

Nowe określenie

 

Gdy baza danych wykonuje procedurę zachowaną, tworzony jest 

plan wykonania

, który pozwala 

na szybsze pobranie informacji w przypadku ponownego wykonania tej samej procedury. Baza 
danych analizuje dane oraz zapytanie i określa najbardziej efektywny sposób pobrania i zwrócenia 
informacji. Sposób ten zapisywany jest następnie w planie wykonania. A zatem, korzyści jakie 
daje stosowanie procedur zachowanych nie wynikają wyłącznie z faktu iŜ są one kompilowane — 
dodatkową zaletą jest stworzenie i późniejsze wykorzystania planu wykonania. 

Wykorzystanie procedur zachowanych pozwala na stworzenie kolejnego poziomu abstrakcji 
pomiędzy stronami ASP.NET a danymi. NaleŜy pamiętać, Ŝe modularność jest jednym z celów 
programowania obiektowego. Dzięki oddzieleniu zapytań SQL od stron ASP.NET moŜna: 

 

pozwolić na wielokrotne stosowanie tych samych zapytań, 

 

ułatwić analizę kodu strony ASP.NET, 

 

zaoszczędzić czas. 

Jeśli wykorzystywane polecenie SQL jest bardzo długie, to umieszczenie go w stronie ASP.NET 
powoduje dodanie do niej kodu, który wcale nie jest tam potrzebny. Takie zapytanie jedynie 
utrudni analizę kodu obsługującego faktyczne moŜliwości funkcjonalne strony. Co więcej, ze 
względu na fakt, iŜ kod zapytania musi zostać przesłany ze strony ASP.NET na serwer bazy 
danych, taki sposób wykonywania zapytań powoduje takŜe niepotrzebne wykorzystanie 
przepustowości łączy. I w końcu, wyobraź sobie, Ŝe to samo zapytanie SQL jest wykorzystywane 
w kilku stronach ASP.NET. Jeśli struktura bazy danych ulegnie jakimkolwiek zmianom i pojawi 
się konieczność zmiany zapytania, to niezbędne poprawki trzeba będzie wprowadzić na kaŜdej ze 
stron, na których dane zapytanie jest uŜywane. W przypadku wykorzystania procedur 
zachowanych zmianę wystarczy wprowadzić w jednym miejscu, a jej skutki obejmą całą aplikację. 

Przeniesienie poleceń SQL do procedur zachowanych eliminuje wszystkie powyŜsze problemy, a 
jednocześnie daje kilka innych korzyści. Implementacja nawet bardzo prostych, jednowierszowych 
zapytań SQL w formie procedur zachowanych da duŜe korzyści.  

Lecz zakończmy te rozwaŜania teoretyczne i stwórzmy w końcu jakąś procedurę zachowaną! 

background image

Tworzenie procedur zachowanych w SQL Serverze 2000 

Procedury zachowane są wykorzystywane w wielu róŜnych systemach baz danych. Na przykład, 
wykorzystują je zarówno SQL Server jak Microsoft Access, choć w kaŜdej z tych baz danych są 
one tworzone w odmienny sposób. W tej części rozdziału pokaŜę jak naleŜy tworzyć procedury 
zachowane w Microsoft SQL Serverze 2000. W następnej części rozdziału zajmiemy się 
Accessem. 

Właśnie z tego powodu, w tej części rozdziału uŜyjemy SQL Servera, pomimo tego, iŜ w 
pozostałych częściach ksiąŜki wykorzystywany był Microsoft Access. Spróbujmy zatem stworzyć 
prostą procedurę zachowaną. 

Otwórz Enterprise Managera, tak samo jak robiliśmy to w rozdziale 8., pt.: „Podstawowe 
wiadomości na temat tworzenia baz danych”. Rozwiń węzły 

Microsoft SQL Server

SQL Server 

Group

, jak równieŜ węzeł z nazwą serwera bazy danych oraz węzeł 

Databases

. Następnie otwórz 

bazę danych 

Banking

 stworzoną w rozdziale 8. W tym celu kliknij symbol „+” wyświetlony przy 

węźle 

Banking

 (patrz rysunek 12.2). 

SQL Server został wyposaŜony w duŜo wbudowanych procedur zachowanych. MoŜna je przejrzeć 
klikając węzeł 

Stored Procedures

, a następnie dwukrotnie klikając jedną z nazw wyświetlonych w 

prawej części okna. Większość z tych predefiniowanych procedur będzie znacznie bardziej 
skomplikowana do procedury którą teraz stworzymy; jednak analizując je będziesz mógł zobaczyć 
jak powinny wyglądać Twoje procedury. Kliknij prawym przyciskiem myszy na ikonie procedur 
zachowanych i z menu podręcznego wybierz opcje 

New Stored Procedure

. Na ekranie pojawi się 

nowe okienko dialogowe, przypominające to pokazane na rysunku 12.3. 

WyraŜenie 

[OWNER].[PROCEDURE NAME]

 zastąp nazwą jaką chcesz nadać tworzonej 

procedurze, na przykład: 

SelectIdFromName

. (W tym przypadku nie musisz zwracać uwagi na 

atrybut 

OWNER

. Więcej informacji na jego temat znajdziesz w dokumentacji SQL Servera 2000.) 

PoniewaŜ chcemy stworzyć sparametryzowane zapytanie, a zatem bezpośrednio po nazwie 
procedury i przed słowem kluczowym 

AS

 naleŜy zdefiniować uŜywane parametry: 

CREATE PROCEDURE SelectIdFromName 
  @FirstName varchar, 
  @LastName varchar, 
  @ID int OUTPUT 
AS 
 

Słowo kluczowe 

OUTPUT

 informuje, Ŝe w danym parametrze naleŜy zapisać wartość i zwrócić ją 

do programu, który wywołał procedurę. Po słowie kluczowym 

AS

 moŜna podać treść zapytania 

SQL: 

SELECT @ID = UserID 
FROM tblUsers 
WHERE FirstName = @FirstName 
  AND LastName = @LastName 
 

PowyŜsze zapytanie pobiera wartość pola 

UserID

 dla uŜytkownika o podanym imieniu i nazwisku 

(polach 

FirstName

 i 

LastName

) i zapisuje ją w parametrze 

@ID

. Później wykorzystamy go jako 

parametr wyjściowy w kodzie strony ASP.NET. Ewentualnie moŜna takŜe kliknąć przycisk 

Check 

syntax

, aby sprawdzić czy kod procedury zachowanej został poprawnie zapisany. SQL Server 

sprawdzi kod procedury i poinformuje Cię jeśli znajdzie w nim jakiekolwiek błędy. Aby zapisać 
procedurę, kliknij przycisk 

OK

. Teraz nazwa naszej procedury zachowanej powinna się pojawić na 

liście, wraz z nazwami procedur predefiniowanych. 

Tworzenie procedur zachowanych w Accessie 2000 

PoniewaŜ we wcześniejszej części ksiąŜki uŜywaliśmy Microsoft Accessa, zatem pokaŜę jak 
moŜna tworzyć procedury zachowane takŜe w tej aplikacji. Access umoŜliwia tworzenie procedur 
zachowanych jednak określa je jako „kwerendy”. Otwórz zatem bazę danych 

Banking

 stworzoną 

w rozdziale 8 i kliknij zakładkę 

Kwerendy

 wyświetloną z lewej strony okna pokazanego na 

rysunku 12.4. 

 

background image

 

Rysunek 12.4. 

W Accessie procedury zachowane są określane jako „kwerendy” 

 

Znasz zasady tworzenia poleceń SQL, a zatem nie musisz korzystać z kreatorów. Dwukrotnie 
kliknij opcję 

Utwórz kwerendę w widoku projektu

. Na ekranie pojawi się  okienko dialogowe o 

nazwie 

Pokazywanie tabeli

, zamknij je klikając przycisk 

Zamknij

. Spójrz na pasek narzędzi 

Accessa, z jego lewej strony powinieneś zauwaŜyć rozwijaną listę o nazwie 

Widok

. Wyświetl jej 

zawartość, a następnie wybierz z niej opcję 

Widok SQL

, tak jak pokazałem na rysunku 12.5. 

 

 

background image

Rysunek 12.5. 

Przejdź do trybu edycji kodu zapytania SQL klikając rozwijaną listę 

Widok

 

wyświetloną z lewej strony paska narzędzi Accessa 

 

Teraz moŜesz pisać kod zapytania SQL bezpośrednio w tworzonej kwerendzie: 

SELECT UserID FROM tblUsers 
WHERE FirstName = @FirstName 
  AND LastName = @LastName 
 

Wpisz kod zapytania w oknie kwerendy, jak pokazałem na rysunku 12.6, a następnie zamknij okno 
klikając przycisk 

X

 widoczny w jego prawym górnym wierzchołku i kliknij przycisk 

Tak

, aby 

zapisać kwerendę. Zapisz kwerendę pod nazwą 

SelectIDFromName

. Teraz powinieneś ją 

zobaczyć na liście wszystkich dostępnych kwerend. 

 

 

Rysunek 12.6. 

Wprowadzanie zapytań w programie Microsoft Access, w widoku SQL 

Notatka 
Mechanizm  obsługi  baz  danych  Accessa  nie  daje  mo

Ŝ

liwo

ś

ci  stosowania  parametrów 

wyj

ś

ciowych  w  kwerendach.  Wła

ś

nie  z  tego  wzgl

ę

du  w  powy

Ŝ

szej  kwerendzie  nie  znajdziesz 

parametru 

@ID

. W dalszej cz

ęś

ci rozdziału dowiesz si

ę

 jak mo

Ŝ

na omin

ąć

 to ograniczenie. 

U

Ŝ

ycie procedur zachowanych w stronach ASP.NET 

Wykonanie procedury zachowanej z poziomu strony ASP.NET jest proste. W tym celu naleŜy 
określić wartość jednej właściwości, której do tej pory nie uŜywaliśmy. Właściwość ta nosi nazwę 

CommandType

dim objCmd as OleDbCommand = new OleDbCommand _ 
    ("SelectIDFromName", Conn) 
objCmd.CommandType = CommandType.StoredProcedure 
 

background image

W pierwszym wierszu powyŜszego fragmentu kodu, w standardowy sposób jest tworzony obiekt 

OleDbCommand

. Jednak tworząc go nie podaliśmy kodu polecenia SQL, lecz nazwę utworzonej 

przed chwilą procedury zachowanej. W 3. wierszu, przypisując właściwości 

CommandType

 

wartość 

StoredProcedure

, informujemy ASP.NET, Ŝe zostanie wykorzystana procedura 

zachowana. Po uzyskaniu tej informacji ADO.NET odszuka procedurę zachowaną w bazie 
danych, wykona ją i zwróci uzyskane informacje wynikowe. 

Jednak takie wykonanie naszej przykładowej procedury zachowanej nie dałoby oczekiwanych 
rezultatów. Przypomnij sobie, Ŝe procedura ta zawierała parametry. Aby zwróciła ona 
jakiekolwiek dane, konieczne będzie określenie wartości parametrów 

@FirstName

 oraz 

@LastName

. MoŜna to zrobić na dwa sposoby — bezpośrednio lub przy wykorzystaniu kolekcji 

OleDbParameters

. Pierwszy z tych sposobów jest bardzo prosty. Wystarczy zmienić pierwszy 

wiersz powyŜszego fragmentu kodu, w sposób przedstawiony na kolejnym przykładzie (przy czym 
wartości są wartościami parametrów jakie naleŜy przekazać): 

dim objCmd as OleDbCommand = new OleDbCommand _ 
    ("SelectIDFromName wartoscwartosc", Conn) 
 

Na przykład: 

dim objCmd as OleDbCommand = new OleDbCommand _ 
    ("SelectIDFromName 'Chris', 'Payne'", Conn) 
 

Metoda ta jest bardzo łatwa, lecz niezbyt efektywna, zwłaszcza jeśli jako parametry 
wykorzystywane są wartości pobierane, na przykład, z elementów sterujących formularzy. W 
przypadku wykorzystania kolekcji parametrów, wartości parametrów naszej przykładowej 
procedury zachowanej moŜna by określić w następujący sposób: 

dim objParam as OleDbParameter 
objParam = objCmd.Parameters.Add("@FirstName", OleDbType.Char) 
objParam.Direction = ParameterDirection.Input 
objParam.Value = tbFirst.Text 
 
objParam = objCmd.Parameters.Add("@LastName", OleDbType.Char) 
objParam.Direction = ParameterDirection.Input 
objParam.Value = tbLast.Text 
 

Ten kod powinien Ci coś przypominać. Dokładnie te same czynności wykonywałeś wcześniej w 
tym rozdziale, w części pod tytułem „Zapytania sparametryzowane”. Teraz moŜesz w standardowy 
sposób wypełnić obiekt 

DataReader

 (wywołując metodę 

ExecuteReader

 obiektu polecenia) i 

związać dane z elementem sterującym wyświetlanym na stronie: 

try 
   objCmd.Connection.Open() 
   objReader = objCmd.ExecuteReader 
catch ex as OleDbException 
   Label1.Text = "Bł

ą

d pobierania informacji z bazy danych." 

end try 
 
DataGrid1.DataSource = objReader 
DataGrid1.DataBind() 
 
objReader.Close 
objCmd.Connection.Close() 
 

A co się stało z naszym parametrem wyjściowym? W Accessie nie da się pobrać wartości 

@ID

 

jako parametru wyjściowego. Niemniej jednak obiekt polecenia zwrócił wartość jako wynik 
wykonania zapytania 

SELECT

. W poprzednim fragmencie kodu moŜna uzyskać dostęp do tej 

wartości za pośrednictwem obiektu 

DataReader

. Na listingu 12.3 został przedstawiony 

kompletny przykład utworzony poprzez połączenie wszystkich wcześniejszych fragmentów kodu, 
wyniki jego pokazano na rysunku 12.7. 

 

Listing 12.3. 

Parametry ułatwiają pobieranie danych 

1

 

<%@ Page Language="VB" %> 

2

 

<%@ Import Namespace="System.Data" %> 

3

 

<%@ Import Namespace="System.Data.OleDb" %> 

4

 

 

background image

5

 

<script runat="server"> 

6

 

   dim Conn as new OleDbConnection("Provider=" & _ 

7

 

            "Microsoft.Jet.OLEDB.4.0;" & _  

8

 

            "Data Source=C:\ASPNET\Data\banking.mdb") 

9

 

    

10

 

   sub SubmitData(obj as Object, e as EventArgs) 

11

 

      dim objCmd as OleDbCommand = new OleDbCommand _ 

12

 

        ("SelectIDFromName", Conn) 

13

 

      dim objReader as OleDbDataReader 

14

 

      objCmd.CommandType = CommandType.StoredProcedure 

15

 

       

16

 

      dim objParam as OleDbParameter 

17

 

      objParam = objCmd.Parameters.Add("@FirstName", _  

18

 

        OleDbType.Char) 

19

 

      objParam.Direction = ParameterDirection.Input 

20

 

      objParam.Value = tbFirst.Text 

21

 

       

22

 

      objParam = objCmd.Parameters.Add("@LastName", _  

23

 

        OleDbType.Char) 

24

 

      objParam.Direction = ParameterDirection.Input 

25

 

      objParam.Value = tbLast.Text 

26

 

       

27

 

      try  

28

 

        objCmd.Connection.Open() 

29

 

        objReader = objCmd.ExecuteReader 

30

 

      catch ex as OleDbException 

31

 

        Response.Write("Bł

ą

d pobierania informacji z bazy danych.") 

32

 

      end try 

33

 

       

34

 

      DataGrid1.DataSource = objReader 

35

 

      DataGrid1.DataBind() 

36

 

       

37

 

      objReader.Close 

38

 

      objCmd.Connection.Close() 

39

 

   end sub 

40

 

</script> 

41

 

 

42

 

<html><body> 

43

 

   <form runat="server"> 

44

 

      Podaj imi

ę

:  

45

 

      <asp:TextBox id="tbFirst" runat="server" /><br> 

46

 

      Podaj nazwisko:  

47

 

      <asp:TextBox id="tbLast" runat="server" /><p> 

48

 

       

49

 

      <asp:Button id="btSubmit" runat="server" 

50

 

         text="Wy

ś

lij" 

51

 

         OnClick="SubmitData"/><p> 

52

 

          

53

 

      <asp:DataGrid id="DataGrid1" runat="server"  

54

 

         BorderColor="black"  

55

 

         GridLines="Vertical"  

56

 

         cellpadding="4"  

57

 

         cellspacing="0"  

58

 

         width="100%" 

59

 

         Font-Name="Arial"  

60

 

         Font-Size="8pt"  

61

 

         HeaderStyle-BackColor="#cccc99" 

62

 

         ItemStyle-BackColor="#ffffff" 

63

 

         AlternatingItemStyle-Backcolor="#cccccc"  

64

 

         AutoGenerateColumns="true" /> 

65

 

   </form> 

66

 

</body></html> 

 

 

background image

 

Rysunek 12.7. 

Zwracanie wartości przez sparametryzowane procedury zachowane 

 

Obiekt 

DataReader

 zawiera jeden wiersz oraz jedną kolumnę, w której znajduje się wartość 

zwrócona przez procedurę zachowaną. 

Notatka 
W  przypadku  SQL  Servera  2000  stosowanie  parametrów  wyj

ś

ciowych  jest  ze  wszech  miar 

zalecane;  a  zatem  mo

Ŝ

na  si

ę

  nimi  posłu

Ŝ

y

ć

  w  powy

Ŝ

szym  przykładzie  i  zrezygnowa

ć

  z 

wykorzystania  obiektu 

DataReader

.  Wi

ę

cej  informacji  na  ten  temat  znajdziesz  we 

wcze

ś

niejszej cz

ęś

ci rozdziału, pt.: „Zapytania sparametryzowane”. 

Parametry wejściowe i wyjściowe są niezwykle przydatne przy przekazywaniu danych do i z 
procedur zachowanych. Istnieją jednak jeszcze inne typy parametrów — takie jak 

InputOutput

 

lub 

ReturnValue

 — których jeszcze nie poznałeś. Wszystkie dostępne rodzaje parametrów 

zostały przedstawione w tabeli 12.2. 

 

Tabela 12.2. 

Rodzaje parametrów (kierunki przekazywania informacji) 

Rodzaj 

Opis 

Input 

Reprezentuje wartość przekazywaną do zapytania. 

InputOutput 

Wartość która moŜe być zarówno przekazana do zapytania jak i zwrócona 
przez nie. 

Output 

Wartość zwracana w wyniku wykonania zapytania. 

ReturnValue 

Reprezentuje wartość zwracaną przez zapytanie, która jednak nie jest 
parametrem. 

 

Przedstawiłem juŜ sposoby wykorzystania parametrów wejściowych (

Input

) oraz wyjściowych 

(

Output

). Parametry 

InputOutput

 są przydatne w sytuacjach, gdy dane przekazane do zapytania 

mogą ulec zmianie (na przykład, w przypadku aktualizacji bazy). Prosty przykład takiego 
zapytania przedstawiłem na poniŜszym przykładzie, w którym wartość pola 

FirstName

 naleŜy 

zmodyfikować w zaleŜności od jego wartości: 

UPDATE tblUsers SET FirstName = "Christopher" 
WHERE FirstName = "Chris" 
 

Zapytanie to moŜna by sparametryzować w następujący sposób: 

background image

UPDATE tblUsers SET @FirstName = "Christopher" 
WHERE @FirstName = "Chris" 
 

W tym przypadku 

@FirstName

 jest zarówno parametrem wejściowym jak i wyjściowym, a po 

wykonaniu polecenia SQL jego wartość ulegnie zmianie. Parametry 

InputOutput

 doskonale 

nadają się właśnie do takich sytuacji.  

Parametry 

ReturnValue

 są bardzo przydatne w poleceniach SQL, które nie zwracają Ŝadnych 

wartości pobranych z kolumn bazy danych. Na przykład, przedstawione poniŜej zapytanie zwraca 
liczbę całkowitą określającą ilość wierszy tabeli: 

SELECT Count(*) FROM tblUsers 
 

Zwracana informacja nie pochodzi z Ŝadnej konkretnej kolumny, a zatem nie jest z nią skojarzona 
Ŝ

adna nazwa pola. Wartość ta jest zwracana przez zapytanie bez Ŝadnej nazwy ani parametru. 

Dane tego typu wspaniale nadają się do obsługi przy uŜyciu parametrów 

ReturnValue

. Aby 

pobrać wartość zwracaną przez powyŜsze zapytanie, naleŜy posłuŜyć się następującym 
fragmentem kodu: 

objParam = objCmd.Parameters.Add("RETURN VALUE", OleDbType.Integer) 
objParam.Direction = ParameterDirection.ReturnValue 
 

Procedury zachowane są niezwykle przydatnym narzędziem, które moŜe poprawić efektywność 
działania aplikacji ASP.NET. Udostępniają one nowe moŜliwości interakcji z bazami danych, 
pozwalając na stosowanie bardzo złoŜonych zapytań i uŜycie bardziej zaawansowanych 
elementów sterujących baz danych. 

Transakcje 

Ile razy wykonywałeś skomplikowane zadanie i w połowie zdawałeś sobie sprawę z tego, Ŝe 
wszystko jest zrobione źle? Czy nie marzyłeś o tym, aby cofnąć czas i zacząć wszystko od nowa? 

Bazy danych są w stanie spełnić to marzenie, a wszystko dzięki 

transakcjom

. Transakcja to zbiór 

pewnych czynności, z których wszystkie muszą zostać wykonane poprawnie lub nie zostanie 
wykonana Ŝadna z nich. Na przykład, wyobraź sobie Ŝe stworzyłeś złoŜoną procedurę zachowaną 
składającą się z 50 poleceń SQL. Jeśli by nie było transakcji, to gdyby któreś z tych poleceń — 
dajmy na to 50-te — zostało wykonane nieprawidłowo, to realizacja całej procedury zostałaby 
przerwana i jedno z poleceń nigdy nie byłoby wykonane. Gdybyś chciał wykonać to polecenie, to 
musiałbyś najpierw ponownie wykonać 49 poleceń poprzedzających je.  

Istnieje bardzo wiele przypadków, gdy takie przerwanie wykonywania serii poleceń jest wysoce 
niepoŜądane. RozwaŜmy przykład aplikacji bankowej. UŜytkownik chce przelać pewną kwotę 
pieniędzy ze swego konta rozliczeniowego, na konto oszczędnościowe. W pierwszej kolejności 
naleŜy zatem odjąć podaną kwotę z konta rozliczeniowego (którego stan jest przechowywany w 
bazie danych), a następnie dodać ją do konta oszczędnościowego (którego stan takŜe jest 
przechowywany w bazie danych). ZałóŜmy, Ŝe pierwszy etap operacji został wykonany 
poprawnie. Jednak podczas próby dodania przelewanej sumy na konto oszczędnościowe okazuje 
się, iŜ zostało ono zablokowane i w danej chwili nie moŜna do niego niczego dodać. O rany, no to 
mamy problem. Kwoty zapisane w bazie danych są nieprawidłowe gdyŜ z kąta rozliczeniowego 
pieniądze juŜ zostały odjęte. 

Transakcje zostały zaprojektowane z myślą o właśnie takich sytuacjach. Jeśli w powyŜszej 
procedurze zostałaby uŜyta transakcja, to nie musielibyśmy się przejmować jakimikolwiek 
problemami jakie mogłyby się wydarzyć w trakcie wykonywania całej operacji. Jeśli cokolwiek by 
się stało, moŜna by bez problemów odtworzyć wykonane czynności. 

Być moŜe przypominasz sobie metody 

AcceptChanges

 oraz 

RejectChanges

 klasy 

DataSet

, o 

których wspominałem w rozdziale 10. Pozwalają one na wykonywanie czynności 
przypominających transakcje, lecz działają wyłącznie na informacjach „odłączonych” (czyli juŜ 
pobranych z bazy danych). Transakcje obejmują swym działaniem całą bazę danych 
wykorzystując przy tym aktywne połączenie, zakładając oczywiście, Ŝe serwer bazy danych w 
ogóle jest w stanie obsługiwać transakcje (większość komercyjnych serwerów baz danych 
dysponuje tą moŜliwością). 

background image

Trzema podstawowymi operacjami kaŜdej z transakcji są — rozpoczęcie transakcji, jej anulacja 
bądź zatwierdzenie. Transakcja zaczyna się w momencie jej rozpoczęcia. Wszystkie kolejne 
czynności są wykonywane i zapisywane w specjalnym dzienniku, dzięki czemu baza danych moŜe 
je później przejrzeć. Anulacja transakcji powoduje odtworzenie wszelkich modyfikacji jakie 
zostały wprowadzone. Baza danych odwołuje się przy tym do dziennika i na jego podstawie jest w 
stanie określić jaką postać miały informacje w momencie rozpoczynania transakcji. Zatwierdzenie 
transakcji sprawia, Ŝe informacje zostają uznane za ostateczne i nie będzie ich juŜ moŜna 
odtworzyć. W konsekwencji, zatwierdzenie oznacza usunięcie z dziennika bazy danych informacji 
o danej transakcji. 

Przyjrzymy się teraz typowemu przykładowi wykorzystania transakcji, przedstawionemu na 
listingu 12.4. 

 

Listing 12.4. 

Zastosowanie transakcji 

1

 

<%@ Page Language="VB" %> 

2

 

<%@ Import Namespace="System.Data" %> 

3

 

<%@ Import Namespace="System.Data.OleDb" %> 

4

 

 

5

 

<script runat="server"> 

6

 

   'deklarujemy polaczenie' 

7

 

   dim Conn as new OleDbConnection("Provider=" & _ 

8

 

            "Microsoft.Jet.OLEDB.4.0;" & _  

9

 

            "Data Source=C:\ASPNET\Data\banking.mdb") 

10

 

    

11

 

   sub Page_Load(obj as Object, e as EventArgs) 

12

 

      dim objTrans as OleDbTransaction 

13

 

      dim objCmd as OleDbCommand = new OleDbCommand _ 

14

 

         ("DELET FROM tblUsers WHERE UserID=32", Conn) 

15

 

          

16

 

      Conn.Open() 

17

 

      objTrans = Conn.BeginTransaction() 

18

 

      objCmd.Transaction = objTrans 

19

 

       

20

 

      try  

21

 

         objCmd.ExecuteNonQuery 

22

 

          

23

 

         objCmd.CommandText = "INSERT INTO tblUsers " & _ 

24

 

            "(FirstName, LastName, Address, City, State, " & _ 

25

 

            "Zip, Phone) VALUES " & _ 

26

 

            "('Jose', 'Santiago', '34 Lake Drive', " & _ 

27

 

            "'Yolktown', 'MA', '02515', '8006579876')" 

28

 

         objCmd.ExecuteNonQuery() 

29

 

         objTrans.Commit() 

30

 

         Label1.Text = "Obie operacje zostały wykonane poprawnie." 

31

 

      catch ex as OleDbException 

32

 

         objTrans.RollBack() 

33

 

         Label1.Text = ex.Message & "<p>" & _ 

34

 

            "

ś

adna operacja nie została wykonana." 

35

 

      finally 

36

 

         objCmd.Connection.Close() 

37

 

      end try 

38

 

   end sub 

39

 

</script> 

40

 

 

41

 

<html><body> 

42

 

   <form runat="server"> 

43

 

      <asp:Label id="Label1" runat="server"  

44

 

         maintainstate=false/> 

45

 

   </form> 

46

 

</body></html> 

 

Analiza 

PowyŜsza strona ASP.NET wykonuje dwa polecenie SQL. Jednak jeśli podczas wykonywania 
któregoś z nich pojawi się nieprzewidziany problem, to w bazie danych nie zostaną wprowadzone 
Ŝ

adne modyfikacje. Na przykład, jeśli drugie polecenie byłoby zapisane w nieodpowiedni sposób, 

to nasza operacja zostałaby przerwana w połowie. Jednak dzięki temu, iŜ przed wykonaniem 
jakichkolwiek czynności rozpoczynamy transakcję (w wierszu 17.), to moŜemy odtworzyć 
wszelkie modyfikacje wprowadzone w bazie w wyniku wykonania pierwszego polecenia. 

background image

W wierszu 7., w standardowy sposób, jest tworzony obiekt 

OleDbConnection

. W wierszu 12. 

jest tworzony obiekt 

OleDbTransaction

, a w wierszu 14. określamy pierwsze polecenie SQL 

jakie zostanie wykonane. Rozpoczęcie transakcji wymaga otworzonego połączenia z bazą danych, 
a zatem, w wierszu 16., otwierane jest połączenie. W wierszu 17. rozpoczynamy transakcję, 
wywołując w tym celu metodę 

BeginTransaction

.  

NaleŜy zwrócić uwagę iŜ 

BeginTransaction

 jest metodą klasy 

OleDbConnection

. Transakcja 

musi bowiem zostać zainicjalizowana przez obiekt połączenia. Ten sposób rozpoczynania 
transakcji został opracowany celowo, aby nie moŜna było stosować transakcji w razie korzystania 
z serwerów baz danych, które ich nie obsługują. Obiekt połączenia jest w stanie określić czy baza 
danych obsługuje transakcje czy nie i uniemoŜliwić rozpoczęcie transakcji jeśli zajdzie taka 
potrzeba. Wszystkie dalsze polecenia (anulowanie transakcji lub jej zatwierdzenie) są 
wykonywane przy uŜyciu obiektu 

OleDbTransaction

W wierszu 18. wskazujemy obiektowi 

OleDbCommand

, który obiekt 

OleDbTransaction

 będzie 

wykorzystywany. Do tego celu słuŜy właściwość 

Transaction

. Wewnątrz bloku 

try

 

wykonujemy polecenie SQL 

DELET

, a następnie tworzymy i próbujemy wykonać polecenie SQL 

INSERT

. Jeśli wszystko pójdzie zgodnie z planem, to będzie moŜna wywołać metodę 

Commit

, aby 

zaakceptować modyfikacje wprowadzone w bazie danych.  

Jeśli jednak coś pójdzie nie tak jak zaplanowaliśmy, to chcemy, aby wszelkie modyfikacje zostały 
odtworzone. Blok 

try

 przechwytuje wyjątek i przekazuje wykonywanie do instrukcji 

catch

gdzie wywoływana jest metoda 

RollBack

 i wyświetlany stosowny komunikat. NiezaleŜnie od 

tego czy został zgłoszony wyjątek czy nie, wykonywany jest blok 

finally

, w którym zamykamy 

połączenie z bazą danych. 

W rezultacie wykorzystania transakcji zostaną wykonane wszystkie polecenia SQL bądź nie 
zostanie wykonane Ŝadne z nich. 

Zaawansowane techniki obsługi danych 
XML 

W poprzednim rozdziale dowiedziałeś się w jaki sposób moŜna wykorzystać język XML do 
przedstawienia niemal kaŜdego typu informacji. Poznałeś takŜe metody otwierania, odczytywania 
oraz zapisywania dokumentów XML z poziomu stron ASP.NET. Niemniej jednak nie są to 
wszystkie moŜliwości wykorzystania i obsługi danych XML. 

W kolejnych częściach tego rozdziału przedstawionych zostanie kilka bardziej zaawansowanych 
technik manipulowania danymi XML. Dowiesz się jak moŜna się poruszać po dokumentach XML 
przy wykorzystaniu obiektów klasy 

XmlNavigator

, który pozwala na wykorzystanie dwóch 

technologii przedstawionych w dalszej części rozdziału — zapytań XPath oraz przekształceń XSL. 
XPath jest językiem zapytań stosowanych do pobierania informacji z dokumentów XML 
(podobnie jak język SQL słuŜy do pobierania informacji z baz danych). Przekształcenia XSL 
pozwalają na zapisanie zawartości dokumentu XML w formie dokumentu strukturalnego 
dowolnego innego typu, na przykład — strony HTML. Dzięki tym technologiom uzyskasz pełną 
kontrolę nad dokumentami XML i ich zawartością. 

XPathDocument 

Nowe określenie

 

W poprzednim rozdziale dowiedziałeś się jak moŜna poruszać się po tekstowych dokumentach 
XML przy wykorzystaniu obiektów klas 

XmlNode

 i 

XmlDocument

. W przypadku prób uzyskania 

dostępu do danych XML, obiekty tych dwóch klas tworzą drzewo węzłów. Oznacza to, Ŝe 
odczytują one zawartość całego pliku XML i tworzą obiektową, hierarchiczną reprezentację 
zapisanych w nim informacji. Najprościej rzecz biorąc, obiekt 

XmlDocument

 pobiera całą 

zawartość pliku XML zanim będzie moŜna uzyskać do niej dostęp. Jednak obiekty klasy 

XPathDocument

 nie tworzą drzew węzłów. Zamiast tego analizują zawartość dokumentu po 

background image

jednym węźle. Obiekty te tworzą obiektową reprezentację węzła gdy zostanie on odczytany. Jeśli 
chcesz, moŜesz je sobie wyobrazić jako dynamiczne obiekty 

XmlDocument

Klasa 

XPathDocument

 przypomina nieco klasę 

XmlDocument

, lecz została stworzona z myślą o 

zapewnieniu jak największej efektywności działania i z tego względu nie dysponuje równie 
bogatymi moŜliwościami. Klasa ta została zoptymalizowana pod kątem wykonywania zapytań 
XPath (stąd teŜ pochodzi jej nazwa — 

XPathDocument

) i przekształceń XSL. Oba te zagadnienia 

— zapytania XPath oraz przekształcenia XSL — zostaną opisane w dalszej części rozdziału. 
Najpierw jednak przyjrzyjmy się sposobowi wykorzystania obiektu 

XPathDocument

 

przedstawionemu na listingu 12.5. 

Listing 12.5. 

Tworzenie dokumentu 

XPathDocument

 

1

 

<%@Page Language="VB" %> 

2

 

<%@Import Namespace="System.Xml" %> 

3

 

<%@Import Namespace="System.Xml.XPath" %> 

4

 

 

5

 

<script runat="server"> 

6

 

   sub Page_Load(obj as object,e as eventargs) 

7

 

      'Tworzymy obiekt XPathDocument' 

8

 

      Dim objDocument as New XPathDocument _ 

9

 

         (Server.MapPath("../rozdzial11/books.xml")) 

10

 

   end sub 

11

 

</script> 

12

 

 

13

 

<html><body> 

14

 

</body></html> 

 

Analiza 

W rzeczywistości kod przedstawiony na powyŜszym listingu nie zawiera niczego nowego — w 
wierszach 8. i 9. jest jedynie tworzony nowy obiekt 

XPathDocument

. W rzeczywistości, to jest 

wszystko co moŜna zrobić z obiektem klasy 

XPathDocument

, nie moŜna go bowiem uŜyć ani do 

poruszania się po zawartości pliku XML ani do jego edycji. Obiekty te zostały stworzone w celu 
zapewnienia szybkiego dostępu do zawartości plików XML i przesyłania jej bezpośrednio do 
innych obiektów, które ją przetworzą. 

Konkretnie rzecz biorąc, z obiektem 

XPathDocument

 najczęściej będzie wykorzystywany obiekt 

XPathNavigator

. Dostarcza on metod słuŜących do poruszania się po zawartości plików XML. 

W jego skład wchodzą wyłącznie te metody, które sprawiają, iŜ jest on efektywnym narzędziem 
nawigacyjnym. Przykład wykorzystania obiektów 

XPathDocument

 oraz 

XPathNavigator

 

przedstawiłem na listingu 12.6. 

 

Listing 12.6. 

Poruszanie się po dokumencie XML przy wykorzystaniu obiektu 

XPathNavigator

 

1

 

<%@Page Language="VB" %> 

2

 

<%@Import Namespace="System.Xml" %> 

3

 

<%@Import Namespace="System.Xml.XPath" %> 

4

 

 

5

 

<script runat="server"> 

6

 

   sub Page_Load(obj as object,e as eventargs) 

7

 

      Dim objDocument as New XPathDocument _ 

8

 

         (Server.MapPath("../rozdzial11/books.xml")) 

9

 

          

10

 

      Dim objNav as XPathNavigator = objDocument. _ 

11

 

         CreateNavigator 

12

 

      objNav.MoveToRoot()  

13

 

      DisplayTree(objNav) 

14

 

   end sub 

15

 

    

16

 

   public sub DisplayTree (objNav as XPathNavigator ) 

17

 

      if (objNav.HasChildren) 

18

 

         objNav.MoveToFirstChild() 

19

 

 

20

 

         Format(objNav) 

21

 

         DisplayTree(objNav)  

22

 

 

23

 

         objNav.MoveToParent() 

24

 

      end if 

background image

25

 

         

26

 

      while (objNav.MoveToNext())         

27

 

         Format (objNav) 

28

 

         DisplayTree (objNav)      

29

 

      end while 

30

 

   end sub 

31

 

 

32

 

   private sub Format (objNav as XPathNavigator) 

33

 

      if Not objNav.HasChildren 

34

 

         if (objNav.NodeType = XPathNodeType.Text) 

35

 

            lblMessage.Text += "" & objNav.Value & "<br>" 

36

 

         end if 

37

 

      else 

38

 

         lblMessage.Text += "&lt;" & objNav.Name & _  

39

 

            "&gt;<br>" 

40

 

 

41

 

         if objNav.HasAttributes 

42

 

            while (objNav.MoveToNextAttribute()) 

43

 

               lblMessage.Text += "&nbsp;&nbsp;&lt;" & _ 

44

 

                  objNav.Name & "&gt; " & objNav.Value & _  

45

 

                  "<br>" 

46

 

            end while 

47

 

 

48

 

            objNav.MoveToParent() 

49

 

         end if 

50

 

      end if 

51

 

    end sub 

52

 

</script> 

53

 

 

54

 

<html><body> 

55

 

   <ASP:Label id="lblMessage" runat="server"/> 

56

 

</body></html> 

 

Znaczna część powyŜszego kodu przypomina przykłady przedstawione w poprzednim rozdziale, 
wykorzystujące obiekty 

XmlDocument

 oraz 

XmlNode

. W wierszach 7. i 8. tworzony jest obiekt 

XPathDocument

, dokładnie w taki sam sposób jak na przykładzie przedstawionym na listingu 

12.5. W wierszach 10. i 11. wywoływana jest metoda 

CreateNavigator

 obiektu 

XPathDocument

. Metoda ta tworzy obiekt 

XPathNavigator

, którego będziemy uŜywali do 

poruszania się po dokumencie XML. Metoda 

MoveToRoot

 wywoływana w wierszu 12. powoduje 

przejście na sam początek pliku XML, i w końcu w wierszu 13. wywoływana jest stworzona przez 
nas procedura 

DisplayTree

Procedura 

DisplayTree

 zdefiniowana w wierszach od 16. do 30, jest procedurą rekurencyjną. W 

pierwszej kolejności określa ona czy aktualnie analizowany węzeł ma jakiekolwiek węzły 
podrzędne. Jeśli ma, to będziemy chcieli wyświetlić informacje o kaŜdym z nich. Wywołanie 
metody 

MoveToFirstChild

 przesuwa kursor do pierwszego węzła podrzędnego. Za samo 

wyświetlenie informacji o węźle na wynikowej stronie WWW odpowiada procedura 

Format

którą niebawem zostanie opisana. W wierszu 21. ponownie wywoływana jest procedura 

DisplayTree

, która powtórzy cały proces dla aktualnie przetwarzanego węzła podrzędnego. 

PowyŜszy proces jest powtarzany dla wszystkich węzłów podrzędnych. Gdy kaŜdy z nich zostanie 
juŜ przetworzony, zostaje wywołana metoda 

MoveToParent

, która przesunie kursor o jeden 

poziom w górę hierarchii dokumentu XML.  

TakŜe druga część procedury jest rekurencyjna. Odpowiada ona za przeanalizowanie węzłów 
znajdujących się na tym samym poziomie hierarchii dokumentu. Do kolejnego węzła na tym 
samym poziomie hierarchii moŜna przejść przy wykorzystaniu metody 

MoveNext

. Metoda ta jest 

wywoływana cyklicznie, aŜ do momentu gdy przetworzone zostaną wszystkie węzły; w tym 
przypadku metoda zwróci wartość 

false

, a wykonywania pętli 

while

 zostanie zakończone. 

Wewnątrz pętli wywoływane są metody 

Format

 oraz 

DisplayTree

. Proces ten jest wykonywany 

aŜ do chwili, gdy wszystkie węzły dokumentu XML zostaną przetworzone. 

Teraz przyjrzyjmy się procedurze 

Format

, zdefiniowanej w wierszach od 32. do 51. Mam 

nadzieję, Ŝe procedura ta Cię nie przeraŜa — przewaŜająca jej część po prostu generuje 
formatujące znaczniki HTML. Instrukcja 

if

 umieszczona w wierszu 33. określa czy dany węzeł 

ma jakiekolwiek węzły podrzędne. Jeśli nie ma, to procedura wyświetli jedynie wartość aktualnie 
przetwarzanego węzła. Jeśli jednak bieŜący węzeł będzie miał jakieś węzły potomne, to 
wyświetlona zostanie jego wartość zapisana w nawiasach kątowych. Kolejna instrukcja 

if

background image

zapisana w wierszu 41., określa czy przetwarzany węzeł ma jakiekolwiek atrybuty i wyświetla 
odpowiedni komunikat, jeśli jakieś atrybut zostaną odnalezione. I w końcu, pętla 

while

 

rozpoczynająca się w wierszu 42. pobiera po kolei wszystkie atrybuty węzła i wyświetla je. 
Wyniki wykonania powyŜszego przykładu przedstawiłem na rysunku 12.8. 

 

 

Rysunek 12.8. 

Wykorzystanie obiektu XPathNavigator do wyświetlania danych XML 

 

XPath 

XPath jest specyfikacją języka słuŜącego do pobierania fragmentów plików XML, opracowaną 
przez Konsorcjum World Wide Web (w skrócie: W3C). Język ten pozwala na zadawanie pytań 
słuŜących do przeszukiwania zawartości plików XML, podobnie jak zapytania SQL słuŜą do 
przeszukiwania informacji przechowywanych w bazach danych. Język XPath moŜe być dosyć 
złoŜony, więc w tym rozdziale nawet nie spróbuję opisywać jego składni. Zamiast tego 
skoncentruję się na zademonstrowaniu sposobu wykorzystania zapytań XPath do przeszukiwania 
dokumentów XML. 

Zapytania XPath są łańcuchami znaków składającymi się ze słów kluczowych reprezentujących 
fragmenty plików XML. Zapytania te są wykonywane przez metodę 

Select

 klasy 

XPathNavigator

. Zakładają, Ŝe chcielibyśmy korzystać z naszego przykładowego pliku 

books.xml

, wywołanie tej metody mogłoby przyjąć poniŜszą, przykładową postać: 

objNav.Select("descendant::book/author/last-name") 
 

PowyŜsze zapytanie zwróci nazwiska wszystkich autorów wszystkich ksiąŜek opisanych w pliku. 
Drugie przykładowe zapytanie XPath zwróci natomiast wyłącznie cenę ostatniej ksiąŜki: 

background image

objNav.Select("//book[last()]/price/text()") 
 

Na listingu 12.7 został przedstawiony przykład prostej strony ASP.NET, która umoŜliwia podanie 
zapytania XPath, a następnie je wykonuje i wyświetla uzyskane wyniki. 

 

Listing 12.7. 

Wykorzystanie zapytań XPath do pobierania danych XML 

1

 

<%@Page Language="VB" %> 

2

 

<%@Import Namespace="System.Xml" %> 

3

 

<%@Import Namespace="System.Xml.XPath" %> 

4

 

 

5

 

<script runat="server"> 

6

 

   sub SelectData(obj as object,e as eventargs) 

7

 

      Dim objDocument as New XPathDocument _ 

8

 

         (Server.MapPath("../rozdzial11/books.xml")) 

9

 

 

10

 

      Dim objNav as XPathNavigator = objDocument.CreateNavigator 

11

 

 

12

 

      lblMessage.Text = "" 

13

 

      try 

14

 

         dim objIterator as XPathNodeIterator = _ 

15

 

            objNav.Select(tbQuery.Text) 

16

 

 

 

 

17

 

         While objIterator.MoveNext() 

18

 

            lblMessage.Text += "&lt;" & _ 

19

 

               objIterator.Current.Name & "&gt; " & _ 

20

 

               objIterator.Current.Value & "<br>" 

21

 

         end while 

22

 

      catch ex As Exception 

23

 

         lblMessage.Text = ex.Message 

24

 

      end try 

25

 

   end sub 

26

 

</script> 

27

 

 

28

 

<html><body> 

29

 

   <form runat="server"> 

30

 

      <h2>Zapytania XPath</h2>  

31

 

      <p> 

32

 

      Na przyład:<br> 

33

 

      <b><code>//book[last()]/@ISBN/text()</b></code> lub  

34

 

      <b><code>descendant::book/author/last-name</b></code><p> 

35

 

       

36

 

      Podaj zapytanie XPath:  

37

 

      <asp:Textbox id="tbQuery" runat=server/> 

38

 

      <asp:Button id="btnSubmit" text="Wykonaj zapytanie" 

39

 

         runat=server OnClick="SelectData"/><p> 

40

 

      <asp:Label id="lblMessage" runat=server/> 

41

 

   </form> 

42

 

</body></html> 

 

Analiza 

W powyŜszym przykładzie, wszystkie najwaŜniejsze czynności wykonywane są w procedurze 

SelectData

, obsługującej zdarzenia generowane przez element sterujący przycisku zdefiniowany 

w wierszach 38. i 39. Kod zapisany w wierszach od 7. do 10. powinien wyglądać znajomo — 
odpowiada on za stworzenie obiektów 

XPathDocument

 oraz 

XPathNavigator

. Prawdziwa 

zabawa zaczyna się natomiast w wierszu 13. gdzie rozpoczyna się blok 

try

. Aby zwrócić 

poszukiwane dane XML, wykorzystywana jest metoda 

Select

, w której wywołaniu zostaje 

podane zapytanie 

XPath

 wpisane przez uŜytkownika w polu tekstowym. Metoda ta zwraca obiekt 

XmlPathNodeIterator

, który pozwala na łatwe przetworzenie uzyskanych wyników. Zwrócone 

wyniki są przetwarzane w pętli 

while

, która, dzięki wykorzystaniu metody 

MoveNext

, pobiera 

kolejno kaŜdy ze zwróconych węzłów. Dla kaŜdego z nich wyświetlana jest nazwa i wartość, przy 
czym informacje te są określane za pomocą właściwości 

Current.Name

 oraz 

Current.Value

Przykładowe wyniki wykonania powyŜszego przykładu, przedstawione zostały na rysunku 12.9. 

 

background image

 

Rysunek 12.9. 

Przeszukiwanie danych XML przy wykorzystaniu zapytań XPath 

 

Język XPath stanowi bardzo potęŜny i doskonały mechanizm słuŜący do pobierania danych XML. 
Dzięki niemu, nie będziesz juŜ musiał wykonywać zapytań posługując się obiektami 

DataSet

Więcej informacji na temat zapytań XPath znajdziesz na witrynie WWW W3C, pod adresem 

http://www.w3.org/TR/xpath

Przekształcenia XSL 

Wszystkie instrukcje XSL są obsługiwane przez procesor przekształceń XSL (określany skrótowo 
jako XslT, od angielskich słów: XSL transform procesor). Język XSL słuŜy do tworzenia arkuszy 
stylów, które informują XslT o tym, w jaki sposób naleŜy przekształcić dane XML. Arkusze 
stylów XSL określają jak XslT ma sformatować dane XML po ich przetworzeniu; podobnie jak 
kaskadowe arkusze stylów informują przeglądarkę w jaki sposób ma sformatować poszczególne 
elementy strony WWW. Na rysunku 12.10 przedstawiłem proces przekształcania jednego 
dokumentu XML na drugi. 

Procesor przekształceń XSL pobiera fragmenty pliku XML wykorzystując w tym celu zapytania 
XPath, a następnie formatuje je na podstawie arkusza stylów XSL. W ASP.NET przekształcenie 
dokumentu XML jest bardzo proste — trzeba tylko podać arkusz stylów XSL. Na listingu 12.8 
przedstawiłem arkusz stylów 

books.xsl

 

Listing 12.8. 

Arkusz stylów XSL 

1

 

<xsl:stylesheet 

2

 

   xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 

3

 

   version="1.0"> 

4

 

   <xsl:template match="/"> 

5

 

      <root> 

6

 

         <xsl:apply-templates/> 

7

 

      </root> 

8

 

   </xsl:template> 

9

 

   <xsl:template match="bookstore"> 

10

 

      <HTML><BODY> 

11

 

         <TABLE width="450"> 

background image

12

 

         <TR> 

13

 

            <TD><b>Title</b></TD> 

14

 

            <TD><b>Price</b></TD> 

15

 

         </TR> 

16

 

         <xsl:apply-templates select="book"/> 

17

 

         </TABLE> 

18

 

      </BODY></HTML> 

19

 

   </xsl:template> 

20

 

   <xsl:template match="book"> 

21

 

      <TR> 

22

 

         <TD><xsl:value-of select="title"/></TD> 

23

 

         <TD><xsl:value-of select="price"/></TD> 

24

 

      </TR> 

25

 

   </xsl:template> 

26

 

</xsl:stylesheet> 

 

Analiza 

PowyŜszy arkusz stylów przekształca dokument XML na dokument HTML. Znaczniki 

xsl:template

 określają w jaki sposób naleŜy przekształcać konkretne fragmenty dokumentu 

XML. Na przykład, fragment arkusza stylów rozpoczynający się w wierszu 20., określa postać 
wszystkich węzłów o nazwie 

book

W tym przypadku przekształcamy dokument XML do postaci dokumentu HTML, co tłumaczy 
obecność znaczników 

HTML

BODY

, itd. Jednak równie łatwo moŜna by przekształcić go do postaci 

innego dokumentu XML — wszystko sprowadza się jedynie do podania odpowiednich 
znaczników. 

Na listingu 12.9 przedstawiony został przykład strony ASP.NET, która wykorzystuje arkusz 
stylów XSL z listingu 12.8, aby przekształcić plik 

books.xml

 do postaci dokumentu HTML. 

 

Listing 12.9. 

Wykorzystanie arkusza stylów XSL oraz procesora przekształceń XSL do 

przekształcenia pliku XML na dokument HTML 

1

 

<%@ Page Language="VB" %> 

2

 

<%@ Import Namespace="System.Xml" %> 

3

 

<%@ Import Namespace="System.Xml.XPath" %> 

4

 

<%@ Import Namespace="System.Xml.Xsl" %> 

5

 

 

6

 

<script runat="server"> 

7

 

   sub Page_Load(obj as object, e as eventargs) 

8

 

      Dim objDocument as New XPathDocument _ 

9

 

          (Server.MapPath("../rozdzial11/books.xml")) 

10

 

 

11

 

      Dim objNav as XPathNavigator = _ 

12

 

          objDocument.CreateNavigator 

13

 

 

14

 

      Dim objXslT As XslTransform = New XslTransform() 

15

 

      dim objWriter as XmlTextWriter = new XmlTextWriter _ 

16

 

             (Server.MapPath("output.html"), nothing) 

17

 

 

18

 

      try 

19

 

         objXslT.Load(Server.MapPath("books.xsl")) 

20

 

         objXslT.Transform(objNav, nothing, objWriter) 

21

 

         objWriter.Close 

22

 

 

23

 

         lblMessage.Text = "Plik został poprawnie zapisany." 

24

 

      catch ex As Exception 

25

 

         lblMessage.Text = ex.Message 

26

 

      end try 

27

 

   end sub 

28

 

</script> 

29

 

 

30

 

<html><body> 

31

 

   <asp:Label id="lblMessage" runat="server" 

32

 

      maintainstate=false/> 

33

 

</body></html> 

 

Analiza 

Pierwszą rzeczą na jaką naleŜy zwrócić uwagę jest dodatkowa przestrzeń nazw — 

System.Xml.Xsl

 — importowana w wierszu 4. W wierszach od 6. do 11. wykonywane są 

background image

standardowe czynności — stworzenie obiektów 

XPathDocument

 oraz 

XPathNavigator

. W 

wierszu 13. tworzony jest obiekt 

XslTransform

, a w wierszu 14. obiekt 

XmlTextWriter

, który 

posłuŜy nam do zapisania przekształconego dokumentu XML w pliku o nazwie 

output.html

Wewnątrz bloku 

try

 plik XSL jest odczytywany i zapisywany w obiekcie 

XslTransform

, który 

wykorzysta arkusz stylów jako schemat na podstawie którego zostanie określona postać nowego 
dokumentu HTML. Następnie wywoływana jest metoda 

Transform

 obiektu 

XslTransform

która przekształci dokument XML zgodnie z arkuszem stylów XSL. Pierwszym argumentem 
wywołania tej metody jest zawartość pliku XML, którą naleŜy przekształcić (przekazana jako 
obiekt 

XPathNavigator

, drugim — dodatkowe parametry jakie naleŜy przekazać do pliku XSL 

(w tym przypadku Ŝadne parametry nie są przekazywane), a trzecim — obiekt 

XmlTextWriter

w którym naleŜy zapisać przekształcone dane XML. 

W końcu, w wierszu 21. zamykany jest obiekt pisarza, a w wierszu 23. wyświetlany krótki 
komunikat informujący o przekształceniu pliku. Po wykonaniu powyŜszego przykładu, w tym 
samym folderze powinien się pojawić plik 

output.html

. Będzie on zawierać informacje pobrane z 

oryginalnego pliku XML, przedstawione na rysunku 12.11. 

 

 

Rysunek 12.11.  Wyniki wykonania przekształcenia XSL zapisane w formie dokumentu HTML 

 

Przekształcone dane XML moŜna by takŜe zapisać w obiekcie 

XmlReader

 i wyświetlić na stronie. 

W tym celu zmienić kod zapisany w wierszu 19. w następujący sposób: 

objReader = objXslT.Transform(objNav, nothing) 
 

W tym przypadku zmienna 

objReader

 jest obiektem 

XmlReader

. I to wszystko. Listing 12.10 

przedstawia pełny kod przykładu wykorzystującego obiekt 

XmlReader

 zamiast obiektu 

XmlTextWriter

 

Listing 12.10. 

Wyświetlanie przekształconych danych XML przy wykorzystaniu obiektu 

XmlReader

 

1

 

<%@ Page Language="VB" %> 

2

 

<%@ Import Namespace="System.Xml" %> 

3

 

<%@ Import Namespace="System.Xml.XPath" %> 

4

 

<%@ Import Namespace="System.Xml.Xsl" %> 

5

 

   

6

 

<script runat="server"> 

7

 

  sub Page_Load(obj as object, e as eventargs) 

background image

8

 

     Dim objDocument as New XPathDocument _ 

9

 

        (Server.MapPath("../rozdzial11/books.xml")) 

10

 

      

11

 

     Dim objNav as XPathNavigator = _ 

12

 

          objDocument.CreateNavigator 

13

 

     Dim objXSLT As XslTransform = New XslTransform() 

14

 

     dim objReader as XmlReader 

15

 

 

16

 

     try 

17

 

        objXSLT.Load(Server.MapPath("books.xsl")) 

18

 

        objReader = objXslT.Transform(objNav, nothing) 

19

 

        While objReader.Read() 

20

 

           Response.Write("<b>" & objReader.Name & "</b> " & _ 

21

 

              objReader.Value & "<br>") 

22

 

        End While 

23

 

 

24

 

        lblMessage.Text = "Plik został poprawnie zapisany." 

25

 

     catch ex As Exception         

26

 

        lblMessage.Text = ex.Message 

27

 

     end try 

28

 

  end sub    

29

 

</script> 

30

 

 

31

 

<html><body> 

32

 

  <asp:Label id="lblMessage" runat="server" 

33

 

     maintainstate=false/> 

34

 

</body></html> 

 

PowyŜszy przykład róŜni się od kodu z listingu 12.9 jedynie tym, iŜ został w nim wykorzystany 
obiekt 

XmlReader

 a nie 

XmlTextWriter

. Z tego względu HTML uzyskany w wyniku 

przekształcenia nie jest zapisywany w pliku. W wierszach od 19. do 22. znajduje się pętla 

while

która przy uŜyciu metody 

Read

 pobiera po kolei wszystkie elementy danych wynikowych i 

wyświetla je. 

Obiekt 

XmlTransform

 dysponuje jedynie dwiema metodami — 

Load

 oraz 

Transform

 — a 

zatem jego wykorzystanie nie powinno przysparzać większych problemów.  

Pamiętasz zapewne, Ŝe procesor przekształceń XSL wykorzystuje zapytania XPath. Plik XSL 
określa nazwy węzłów, które naleŜy przekształcić. Obiekt 

XmlTransform

 wykorzystuje zapytania 

XPath do pobrania węzłów o określonych nazwach, przy czym Ty jako programista nawet nie 
wiesz w jaki sposób cały ten proces jest realizowany. Równie dobrze moŜna by samemu uŜyć tych 
zapytań o pobrania danych, a następnie je sformatować. Jednak po co się męczyć jeśli obiekty 

XmlTransform

 mogą zrobić to za nas? 

Więcej informacji na temat XSL moŜna znaleźć na witrynie W3C, na stronach: 

http://www.w3.org/TR/xsl

 oraz 

http://www.w3.org/TR/xslt

To nie jest ASP! 

Wiele spośród technik opisanych w tym rozdziale jest takŜe dostępnych we wcześniejszej, 
tradycyjnej wersji technologii ASP. Na przykład, sparametryzowane procedury zachowane były 
kiedyś niezwykle popularnym sposobem wykonywania zapytań SQL. TakŜe operacje na danych 
XML moŜna było wykonywać, choć był do tego potrzebny specjalny, dodatkowy komponent 
ASP. ASP.NET udostępnia jednak znacznie prostsze sposoby wykonywania tych wszystkich 
czynności, gdyŜ wszystkie konieczne moŜliwości funkcjonalne są wbudowane bezpośrednio w 
ś

rodowisko .NET i są w pełni obiektowe. 

Wielu programistów ASP spotkało się juŜ z omawianymi tu zagadnieniami, a zatem 
wykorzystanie ich w środowisku .NET nie powinno przysparzać większych trudności. Zmianie 
uległ jedynie sposób implementacji; wciąŜ moŜna natomiast korzystać z istniejących procedur 
zachowanych, arkuszy stylów i zapytań XPath. Jedyne co będziesz musiał zrobić, to korzystać z 
nich przy uŜyciu innych obiektów.