Przykładowa aplikacja jest narzędziem internetowym przeznaczonym do zarządzania projektami i zadaniami. Pomysł polegał na tym, by polepszyć produktywność zespołu przez wprowadzenie jego członków do zarządzania projektami i zadaniami. Celem tworzenia aplikacji było opracowanie prostego interfejsu internetowego, który pozwoli użytkownikom na sporządzanie i zmianę projektów i zadań oraz ustawienie interfejsu przez ustawienie różnych opcji sortowania i filtrowania.
Wsparcie dla Extensible Markup Language (XML) oraz właściwości
XML zawartych w Microsoft® SQL Server™ 2000 pozwala programistom na budowę stron
Web oraz zaawansowanych aplikacji baz danych, które funkcjonują na różnych platformach
systemowych oraz językach programowania. Wsparcie dla XML i Microsoft .NET Framework
w SQL Server od wersji SQL Server 2000 i dodanie do SOAP Web Services wsparcia dla
SQL Server dalej rozwinęło te możliwości. Przykładowa aplikacja, opisana w tym dokumencie,
demonstruje, jak można używać Microsoft SQLXML 3.0 i Microsoft Visual Basic® .NET
do zbudowania rozszerzalnej i skalującej się strony Web.
Opis przykładowej aplikacji
Przykładowa aplikacja „Projekty i system śledzenia zadań” jest narzędziem internetowym
przeznaczonym do zarządzania projektami i zadaniami. Pomysł polegał na tym, by polepszyć
produktywność zespołu przez wprowadzenie jego członków do zarządzania projektami
i zadaniami. Celem tworzenia aplikacji było opracowanie prostego interfejsu internetowego,
który pozwoli użytkownikom na sporządzanie projektów i zadań, na zmianę projektów
i zadań oraz ustawienie interfejsu przez ustawienie różnych opcji sortowania i filtrowania.
Dane o określonych projektach i zadaniach są zapisywane w bazie danych SQL Server
2000, która zawiera także informacje pracowników, dotyczące ustawień i opcji (sortowania
i filtrowania) w projektach i zadaniach.
SQLXML 3.0 został użyty do stworzenia aplikacji przede wszystkim klas zarządzających
(Managed Classes) SQLXML, diagramów aktualizujących (updategrams), plików
z szablonami XML, wsparcia serwisów Web (SOAP). Pliki szablonów XML, które zawierają
zapytania SELECT...FOR XML, są używane do pobierania danych. Pliki diagramów aktualizujących
(updategrams) są używane do wykonywania wszystkich operacji modyfikacji bazy
danych (insert i update). Klasy zarządzające SQLXML (SQLXML Managed
Classes) służą do uruchamiania plików szablonów XML oraz diagramów aktualizujących.
Zanim zaczniemy ustawiać aplikację, należy przyjrzeć się strukturze bazy danych
oraz przykładowym danym.
Struktura bazy danych
Baza danych Projects zawiera następujące tablice:
- tblEmployees
- tblEmpPreferences
- tblProjects
- tblDepartments
- tblStatusCodes
- tblPriorityCodes
- tblTasks
Kolumny tych tablic przedstawione są na poniższym diagramie bazy danych:

Rysunek 1. Struktura bazy danych Projects
Tabela tblEmployees zawiera informacje o pracownikach, tzn. trzy rekordy
z informacjami o pracownikach, jak pokazano na poniższym przykładzie. Pole EmailAlias
jest używane do logowania się do systemu.
| Row_ID |
FirstName |
LastName |
EmailAlias |
DeptCode |
| 1 |
Alan |
Steiners |
Alan |
10 |
| 2 |
Kim |
Ralls |
Kim |
1 |
| 3 |
Bradley |
Beck |
Bradley |
1 |
Tabela tblEmpPreferences jest używana do przechowywania informacji o preferencjach
w sortowaniu i filtrowaniu, wybranych przez pracowników. Użycie bazy danych po stronie
serwera do przechowywania danych (w przeciwieństwie do plików cookie po stronie
klienta) pozwala pracownikom na użycie dowolnego komputera przy takich samych ustawieniach,
jakie wybrali wcześniej.
Tablice tblProjects i tblTasks mają prawie taką samą strukturę,
zawierają też niezależnie od siebie informacje o projektach i zadaniach.
Tabela tblPriorityCodes zawiera kody priorytetów. Przykładowa baza danych
definiuje trzy priorytety: średni (Medium), niski (Low) i wysoki (High).
Tabela tblDepartments zawiera nazwy różnych działów firmy.
W tabeli tblStatusCodes znajdują się informacje o statusie projektu lub
zadania. Poszczególne kody statusu zawierają: nie rozpoczęte (Not Started), w trakcie
(In Progress), zakończone (Completed), oczekujące (Waiting), w trakcie (Ongoing),
osiągnięte (Achieved), wstrzymane (Deferred) i anulowane (Cancelled).
Dostęp użytkownika do przykładowej aplikacji
Kiedy pracownik po raz pierwszy odwiedza intranetową stronę Projekty (Projects),
jest proszony o podanie firmowego adresu e-mail. W zależności od wprowadzonego adresu
e-mail, preferencje użytkownika pobierane są z tabeli tblEmpPreferences i
przekierowywane do okna Projekty (Projects) lub do okna Zadań (Tasks),
stosownie do preferencji wyszczególnionych w ustawieniach pracownika. Plik cookie
(zapisywany po stronie przeglądarki klienta) jest używany do określenia, czy pracownik
odwiedza stronę po raz pierwszy, czy ponownie.
Pracownicy mogą przeglądać wszystkie projekty lub filtrować listę danych przez
wybór wydziału, właściciela, statusu lub priorytetu albo przez połączenie tych pozycji.
Okno Projektów pozwala pracownikom na wprowadzanie zmian do istniejących
projektów, przeglądanie zadań dla projektów lub dodawanie nowych projektów. Okno
Zadań pozwala pracownikom na przeglądanie wszystkich lub przefiltrowanych
zadań, dodanie nowych zadań lub zmianę istniejących.
W tej aplikacji nie zostało zaimplementowane sprawdzanie bezpieczeństwa. Wszystkie
dane są dostępne dla wszystkich.
Zakładka Opcje (Options) pozwala pracownikom na określenie sposobu, w
jaki informacje mają być sortowane, określenie dodatkowych kryteriów filtrowania
sortowania oraz na zalogowanie się do systemu jako inny użytkownik.
Zakładka Administrator (Admin) pozwala administratorowi na zarządzanie
pracownikami, wydziałami, kodami statusu i kodami priorytetów.
Architektura przykładowej aplikacji
System zarządzania projektami i zadaniami składa się z trzech podstawowych komponentów:
- SQL Server 2000, który zawiera bazę danych Projects.
- Microsoft Internet Information Services (IIS 5), zawierający wirtualny katalog
strony internetowej, który zawiera pliki źródłowe ASP.NET − napisane przy użyciu
Visual Basic .NET. Serwer internetowy zawiera także wirtualny katalog SQLXML
3.0, który wskazuje na bazę danych Projects. Ten wirtualny katalog zawiera
dwie wirtualne nazwy − Szablony (Templates) i SQLXMLWebSvc. Nazwa wirtualna
Szablony (Templates) jest typu szablon (template) − zawiera pliki
szablonów XML i pliki diagramów aktualizujących (updategram). Nazwa wirtualna
SQLXMLWebSvc jest typu soap i jest używana do wywoływania metod
usługi WWW, która z kolei wywołuje przechowywane procedury SQL serwera bazy
danych SQL Server 2000.
- Klient przeglądarki lub klient aplikacji Microsoft Visual Basic 6.0. Klient
przeglądarki używa strony ASP.NET i wykonuje żądania dla stron WWW z rozszerzeniem.aspx.
Aplikacja Visual Basic 6.0 jest klientem usługi WWW, która pozwala na przeglądanie
statystyk projektów i zadań. Ta aplikacja używa Microsoft SOAP Toolkit 2.0 do
tworzenia zapytań SOAP, a Microsoft XML Core Services (MSXML 4.0) do przetwarzania
odpowiedzi.

Rysunek 2. Architektura przykładowej aplikacji
Strony WWW (pliki .aspx) używają klas zawartych w Components.dll
do tworzenia zapytań do bazy danych i innych zadań, takich jak: zastosowanie arkuszy
XSLT (Extended Stylesheet Language Tranformations) i wyznaczanie wyrażeń języka
XPath.
Components.dll zawiera jedną klasę dla każdej tabeli w bazie danych. Wszystkie
te klasy używają klasy DBAccess, która zawiera ogólne metody dla wywoływania i przetwarzania
plików szablonów SQLXML. Klasa narzędziowa wewnątrz Components.dll udostępnia metody
pozwalające na zastosowanie arkuszy stylów, wykonywanie wyrażeń XPath itp.
Klasa DBAccess wewnątrz Components.dll używa klas zarządzających SQLXML 3.0 do
wykonywania plików szablonów XML i diagramów aktualizacji. Pozwala też na uruchomienie
szablonu ciągu znaków i szablonu pliku.
Klient aplikacji Visual Basic jest klientem usługi WWW używającej SOAP i wysyła
żądania SOAP bezpośrednio do wirtualnej nazwy SQLXML 3.0. (sposób skonfigurowania
wirtualnej nazwy SQOP, by wskazywała na przechowywane procedury w serwerze SQL Server
2000, przedstawiono w następnej części artykułu). W tej aplikacji znajdują się dwie
przechowywane procedury: jedna, która zwraca statystykę projektów, druga zwracająca
statystykę zadań. Obydwie te procedury są metodami serwisów WWW, które są udostępnione
przez skonfigurowanie wirtualnej nazwy SOAP. Aplikacja kliencka Visual Basic wywołuje
te metody serwisu WWW, następnie analizuje odpowiedź i wyświetla wyniki.
Wymagania dla budowy i testowania przykładowej aplikacji
By zbudować i testować intranetową stronę WWW, potrzebne są następujące narzędzia:
- Microsoft Windows® 2000 lub Windows XP
- Microsoft Internet Information Services 5.0 (IIS 5), lub nowszy
- Microsoft SQL Server 2000 (z Service Pack 2)
- Microsoft.NET Framework
- Microsoft Visual Studio®.NET
- Windows Internet Explorer 5.0, lub nowszy
Natomiast przy sprawdzaniu klienta SOAP usług WWW napisanego w języku Visual
Basic:
- Microsoft Visual Basic 6.0
- Microsoft XML Core Services 4.0 (MSXML)
- Microsoft SOAP Toolkit 2.0 Service Pack 2
Instalacja aplikacji
Ustawienie Intranetu, by uruchomić aplikację, pociąga za sobą następujące zadania:
- Instalacja plików aplikacji
- Dołączenie plików bazy danych do serwera SQL Server 2000
- Stworzenie wirtualnego katalogu IIS
- Stworzenie wirtualnego katalogu SQLXML 3.0
- Stworzenie nazwy wirtualnej SQLXML
- Kompilacja projektu
- Aktualizacja zmiennych konfiguracyjnych
Instalacja plików aplikacji
- Rozpakowanie pliku projects.zip i przeniesienie zawartości do katalogu C:\Projects.
- Po rozpakowaniu plików aplikacji będzie widoczna struktura katalogu − jak
na przykładzie na rysunku 3.

Rysunek 3. Struktura katalogu System śledzenia projektów i zadań
Dołączanie plików bazy danych do serwera SQL Server 2000
- Po przejściu do folderu Projects, a następnie do Components należy otworzyć
folder Database, a następnie rozpakować plik DatabaseFiles.zip, zawierający
pliki.MDF and.LDF, które trzeba dołączyć do serwera SQL Server 2000.
- Uruchomić program Enterprise Manager (wchodzi w skład serwera SQL Server
2000), i rozwinąć węzeł Server.
- Kliknąć prawym przyciskiem myszy Bazę danych (Databases), wybrać
Wszystkie zadania (All Tasks), a następnie Dołącz bazę danych
(Attach Database).
Tworzenie wirtualnego katalogu IIS
- Uruchomić Menedżera Usług Internetowych (Internet Services Manager).
- Utworzyć nowy katalog wirtualny, nazwać go Projects i wskazać jego katalog
źródłowy na C:\Projects\Web.
Zamiast tego, można wykonać następujące operacje:
- W C:\Projects kliknąć prawym przyciskiem na folder Web folde i wybrać Właściwości
(Properties).
- Wybrać zakładkę Udostępnianie w sieci (WebWeb Sharing), a następnie
Udostępnij ten folder (Share this folder).
- Zmienić nazwę z Web na Projects.
Tworzenie wirtualnego katalogu SQLXML 3.0
- W menu Start wybrać Programy, następnie SQLXML 3.0 i kliknąć ConRysunek IIS
Support.
- Uruchomić IIS Virtual Directory Management for SQLXML 3.0.
- Stworzyć nowy katalog wirtualny SqlXml z nazwą ProjectsSQLVirDir. Podłączyć
nowy katalog wirtualny do C:\Projects\SQLVirDir. W oknie właściwości ProjectsSQLVirDir,
w zakładce Security w polu User Name i Password wpisać swoją nazwę użytkownika
i hasło do SQL Servera.
- W zakładce Data Source wybrać instancję SQL Servera, do którego należy
podłączyć bazę danych.
- Wybrać bazę danych Projects w polu Database.
- W zakładce Settings zaznaczyć pola wyboru Allow template queries
i Allow POST.

Rysunek 4. Tworzenie wirtualnego katalogu SQLXML
Tworzenie wirtualnej nazwy SQLXML
- W oknie Właściwości ProjectsSQLVirDir w zakładce Virtual Names
w polu Name należy wpisać Templates.
- W polu Type wpisać template.
- W polu Path wpisać C:\Projects\SQLVirDir\Template.
Kompilacja projektu
- Należy otworzyć projekt ProjTaskTrackSystem.sln w Visual Studio.NET.
Ten projekt zawiera dwa podprojekty: Components i ProjTrackWeb. W pierwszej kolejności
należy skompilować projekt Components, a następnie dodać do niego odniesienie (reference)
w projekcie ProjTrackWeb.
- W projekcie ProjTrackWeb kliknąć prawym przyciskiem References.
- Wybrać Add Reference.
- Wskazać plik Components.dll i dodać odniesienie (reference).
Aktualizacja zmiennych konfiguracyjnych
Plik Web.config w projekcie ProjTrackWeb definiuje dwie zmienne. Pierwsza
zawiera informacje o połączeniu z serwerem SQL Server 2000 (connection string),
druga − ścieżkę do katalogu, gdzie znajdują się pliki szablonów XML i diagramy
aktualizacji. Należy tu poprawić zmienne konfiguracyjne na właściwe połączenie
z bazą danych oraz właściwą ścieżkę do katalogu z szablonami.
Uruchamianie przykładowej aplikacji
Strona default.aspx jest wczytywana domyślnie; używa ona pliku cookie
do sprawdzenia, czy pracownik odwiedza stronę po raz pierwszy. Jeżeli plik cookie
nie zostanie znaleziony, przeglądarka będzie przekierowana do strony firstvisit.aspx.

Rysunek 5. Wstępny widok dla użytkownika pierwszy raz odwiedzającego stronę
Do uruchomienia przykładowej aplikacji należy użyć jednego z e-maili z przykładowych
danych pracownika. Adresy e-mail są sprawdzane na podstawie danych pracowników z
tablicy tblEmployees. Jeżeli zostaną znalezione pasujące rekordy, tablica
tblEmpPreferences jest przeszukiwana w celu uzyskania preferencji pracownika.
Na podstawie tych ustawień pracownik jest przekierowywany do zakładki Projekty
(Projects) lub zakładki Zadania (Tasks). Jeżeli nie zostaną
znalezione żadne preferencje, pracownik zostanie przekierowany domyślnie do zakładki
Projekty.

Rysunek 6. Zakładka Projekty (Projects)
Chcąc utworzyć nowy projekt, pracownik musi kliknąć New Project, który
otwiera okno dialogowe New Project (rysunek 7).

Rysunek 7. Okno dialogowe Nowy Projekt (New Project)
W celu edycji istniejącego projektu lub przeglądania zadań dla projektu pracownik
klika rekord projektu w polu Title w zakładce Project, które otwiera
okno dialogowe Edit Project (rysunek 8).

Rysunek 8. Okno dialogowe edycja projektu (Edit Project)
Zakładka Tasks jest podobna do zakładki Projects. Użytkownik może
zobaczyć listę zadań i nacisnąć New Task, by stworzyć nowe zadanie lub kliknąć
pojedyncze zadanie w polu Title w celu edycji.

Rysunek 9. Zakładka Zadania (Tasks)
Zakładki Projects i Tasks udostępniają pola na dole strony, które
pozwalają pracownikowi na filtrowanie oglądanej listy projektów i zadań. System
pozwala na selektywne wybieranie danych według właściciela, statusu, priorytetu
i wydziału. Ustawienia tego filtra zapisywane są w tablicy tblEmpPreferences.

Rysunek 10. Wygląd listy projektów filtrowanej po właścicielu
Zakładka Options (rysunek 11) umożliwia pracownikowi sprecyzowanie kolejnych
ustawień, takich jak: pola sortowania dla projektów i zadań, początkową stronę (Projects
lub Tasks), i włączenia i wyłączenia podglądu zarchiwizowanych lub anulowanych
projektów lub zadań. Pozwala także na przełączanie pomiędzy użytkownikami poprzez
kliknięcie Change.

Rysunek 11. Zakładka Options
Zakładka Admin pozwala administratorowi na zarządzanie tablicami bazy
danych (polami tablic Employees, Departments, Status Codes
i Priority Codes). Rysunek 12 pokazuje stronę Employees.

Rysunek 12. Zakładka administratora (Admin)
Components.dll
Components.dll (przestrzeń adresowa Projects.Components) zawiera klasy, które
obudowują dostęp do danych, obsługę błędów i funkcjonalność XPath/XSLT (rysunek
13). Plik ErrorHandler.vb natomiast zawiera jedną współdzieloną (statyczną) metodę,
nazwaną Log, która dodaje wiadomość do dziennika zdarzeń systemu Windows.

Rysunek 13. Pliki klas w projekcie komponentów Visual Basic .NET
Pliki tblXXXX.vb udostępniają metody dostępowe do poszczególnych tabel bazy danych.
Wszystkie te metody używają klasy DBAccess do wywołania pliku szablonu XML lub diagramu
aktualizującego, mających dostęp do danych.
Klasa DBAccess
Klasa DBAccess używa zarządzanych klas SQLXML do wywołania szablonów XML i diagramów
aktualizacji. Konstruktor klasy pierwszy otrzymuje ciąg połączenia do bazy danych
z pliku Web.config i następnie inicjuje prywatną składową zmiennej SqlXmlCommand
przez pokazanie ciągu połączenia.
Imports System
Imports System.Collections
Imports System.IO
Imports System.Configuration
Imports Microsoft.Data.SqlXml
Imports System.Xml
Imports System.Xml.XPath
Namespace Projects.Components
Public Class DBAcess
Private SQLDBConnStr As String
Private TemplatesDir As String
Private SqlXmlCmdObj As SqlXmlCommand
'Konstruktor: Inicjalizacja
Public Sub New()
Try
SQLDBConnStr = ConfigurationSettings.AppSettings("DBConnStr")
TemplatesDir = ConfigurationSettings.AppSettings("SQLXMLTemplatesDir")
SqlXmlCmdObj = New SqlXmlCommand(SQLDBConnStr)
Catch e As Exception
ErrorHandler.Log(e.ToString())
End Try
End Sub
Użycie współdzielonej właściwości AppSettings klasy ConfigurationSettings
pozwoli na otrzymanie połączenia z bazą danych i wartości SQLXMLTemplatesDir. Następnie
należy utworzyć obiekt SqlXmlCommand i przydzielić go do lokalnej zmiennej.
Obiekt SqlXmlCommand jest używany w pozostałych metodach klasy do udostępnienia
funkcjonalności SQLXML.
Klasa DBAccess zawiera metody, które pozwalają na wykonywanie szablonów SQLXML.
Szablony te są używane do uruchamiania zapytań i pobierania danych w formacie XML
lub do uruchamiania diagramów aktualizacji i modyfikacji bazy danych. Metoda
ExecuteTemplate pobiera szablon jako ciąg znaków podany w parametrze. Metoda
ExecuteTemplateFile pobiera plik szablonu XML, który zawiera zapytanie SQL
lub tekst diagramu aktualizacji.
'Uruchomienie tekstu szablonu – brak parametrów (Execute Template text - no parameters)
Public Function ExecuteTemplate(ByVal TemplateText As String) As String
SqlXmlCmdObj.CommandType = SqlXmlCommandType.Template
SqlXmlCmdObj.CommandText = TemplateText
Return RunTemplate()
End Function
'Uruchomienie pliku szblonu (no parameters)
Public Function ExecuteTemplateFile(ByVal TemplateFile As String) As String
SqlXmlCmdObj.CommandType = SqlXmlCommandType.TemplateFile
SqlXmlCmdObj.CommandText = TemplatesDir & TemplateFile
Return RunTemplate()
End Function
Obie te metody są przeciążone w celu pobrania kolekcji obiektów, potrzebnych
do przekazania parametrów do szablonów SQLXML. Przeciążone metody używają klasy
SqlXmlParameter do stworzenia parametrów i ustawienia ich nazw i wartości. Poniżej
znajduje się dodatkowy kod w przeciążonych metodach, które umożliwiają przekazywanie
parametrów w trakcie wykonywania szablonów SQLXML:
Dim ParamEnum As IDictionaryEnumerator = Params.GetEnumerator()
While ParamEnum.MoveNext()
Dim aParam As SqlXmlParameter = SqlXmlCmdObj.CreateParameter()
aParam.Name = ParamEnum.Key
aParam.Value = ParamEnum.Value
End While
Uruchamianie szablonu i sprawdzanie błędów wykonywane jest we wspólnej funkcji,
nazwanej RunTemplate, znajdującej się w klasie DBAccess.
Private Function RunTemplate() As String
Try
Dim ResultStream As Stream
Dim ResultString As String
ResultStream = SqlXmlCmdObj.ExecuteStream()
Dim SR As New StreamReader(ResultStream)
ResultString = SR.ReadToEnd()
'Sprawdzenie błędów
Try
Dim ResultStrReader As New StringReader(ResultString)
Dim ResultXmlReader As New XmlTextReader(ResultStrReader)
Do While ResultXmlReader.Read()
If ResultXmlReader.NodeType = XmlNodeType.ProcessingInstruction Then
If ResultXmlReader.Name = "MSSQLError" Then
ErrorHandler.Log(ResultXmlReader.Value)
End If
End If
Loop
Catch
End Try
Return ResultString
Catch e As Exception
ErrorHandler.Log(e.ToString())
Return "<Error>" & e.ToString() & "</Error>"
End Try
End Function
Klasa SqlXmlCommand uruchamia metodę ExecuteStream, która służy do wykonania
szablonu i pobrania wyników − jako nowy obiekt typu strumień danych. Ważne jest,
by zapamiętać, że jeżeli wykonanie szablonu się nie uda i wynikowy strumień danych
zwróci błąd SQLXML, żaden wyjątek nie jest generowany, a błąd nie jest wywoływany.
Powód tego jest taki, że z perspektywy .NET Framework wykonanie szablonu się powiodło,
natomiast do użytkownika należy sprawdzenie zwróconego dokumentu XML, by zobaczyć,
czy wykonanie szablonu się powiodło, czy nie.
Do obsługi błędów należy stworzyć obiekt XmlTextReader dla zwróconego
strumienia danych XML i następnie sprawdzić, czy pokazała się instrukcja MSSQLError.
Po jej znalezieniu należy zapisać informacje o błędzie w systemowym dzienniku zdarzeń
Windows. Dla przykładu, jeżeli wykonany zostanie diagram aktualizujący dla komendy
insert i jeżeli wykonanie to się nie powiedzie z powodu braku wymaganej kolumny
– diagram aktualizujący zwróci ciąg znaków XML, który zawiera informacje z opisem
błędu, ale .NET Framework nie wywoła wyjątku lub błędu, ponieważ wykonanie diagramu
aktualizującego samo w sobie powiodło się.
Klasy tblXXXX
Components.dll zawiera pliki klas dla każdej tabeli w bazie danych Projects.
Na przykład tblDepartments.vb jest plikiem dla tabeli tblDepartments i tak
dalej. Klasy tblXXXX używają klasy DBAccess dla wywołania plików szablonu i diagramów
aktualizujących. Poniżej pokazano przykład, jak wygląda klasa tblDepartments.vb:
Namespace Projects.Components
Public Class tblDepartments
Private DBAccObj As New DBAcess()
Public Function GetAllDepartments() As String
Return DBAccObj.ExecuteTemplateFile("GetAllDepartments.xml")
End Function
Public Function GetDeptByID(ByVal Row_ID As String) As String
Dim ParamsCollection As New Collections.Hashtable()
ParamsCollection.Add("@Row_ID", Row_ID)
Return DBAccObj.ExecuteTemplateFile("GetDeptByID.xml", _
ParamsCollection)
End Function
Public Function Insert( _
ByVal DataValues As Collections.Hashtable) As String
Return DBAccObj.ExecuteTemplateFile("InsertDept.xml", DataValues)
End Function
Public Function Update(_
ByVal DataValues As Collections.Hashtable) As String
Return DBAccObj.ExecuteTemplateFile("UpdateDept.xml", DataValues)
End Function
Public Function Delete(ByVal Row_ID As Integer) As String
Dim ParamsCollection As New Collections.Hashtable()
ParamsCollection.Add("@Row_ID", Row_ID)
Return DBAccObj.ExecuteTemplateFile("DeleteDepartment.xml",
ParamsCollection)
End Function
End Class
End Namespace
Metoda GetAllDepartment wywołuje metodę ExecuteTemplateFile w klasie
DBAccess, przekazując nazwę pliku szablonu XML (GetAllDepartments.xml), który ma
zostać wykonany. Oto jak wygląda plik szablonu GetAllDepartments.xml:
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<!--All Departments-->
<sql:query>
SELECT * FROM tblDepartments FOR XML AUTO
</sql:query>
</ROOT>
Plik szablonu zawiera zapytanie SELECT w tabeli tblDepartments i używa
klauzuli FOR XML AUTO, która informuje procesor zapytania, by zwrócił wyniki jako
strumień XML w miejsce rekordów (dopóki opcja Run on the client jest wybrana,
oznacza to,że konwersja jest wykonywana po stronie klienta zamiast po stronie serwera
SQL Server).
Podobnie, metody Insert, Update, Delete, i GetDeptByID
używają klasy DBAccess i wykonują poszczególne diagramy aktualizacji lub pliki szablonów
przekazując parametry, jeżeli są wymagane.
Pozostałe klasy tblXXXX wyglądają podobnie jak przykład z plikiem klasy tblDepartments.vb
przedstawionym wcześniej.
Poniższy kod jest przykładem tego, jak parametry są przekazywane do szablonów
SQLXML. Klasa tblProjects zawiera metodę, nazwaną GetProjectDetails, która
pobiera ProjectRowID jako parametr i przekazuje go do pliku GetProjectDetails.xml
− szablonu SQLXML.
Public Function GetProjectDetails(ByVal ProjectRowID As String) _
As String
Dim ParamsCollection As New Collections.Hashtable()
ParamsCollection.Add("@ProjectRowID", ProjectRowID)
Return DBAccObj.ExecuteTemplateFile("GetProjectDetails.xml", _
ParamsCollection)
End Function
A oto przykład, jak wygląda plik GetProjectDetails.xml:
<ROOT xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<!--A Project Details-->
<sql:header>
<sql:param name="ProjectRowID"></sql:param>
</sql:header>
<sql:query>
SELECT *,
CONVERT(varchar(10), tblProjects.StartDate, 101) as StartDate1,
CONVERT(varchar(10), tblProjects.DueDate, 101) as DueDate1
FROM tblProjects
WHERE Row_ID = @ProjectRowID
FOR XML AUTO
</sql:query>
</ROOT>
Domyślnie klauzula FOR XML zwraca wartości typu data w formacie 2002-03-01T00:00:00.
Poprzedni plik szablonu używa funkcji CONVERT języka Transact-SQL, by otrzymać datę
w formacie mm/dd/yyyy. Ten plik szablonu przyjmuje parametr ProjectRowID, dla którego
żądane są szczegóły projektu.
Mimo że wirtualna nazwa szablonów została stworzona wcześniej, ta nazwa właściwie
nie jest użyta w kodzie. Klasy zarządzające SQLXML są używane i fizyczna ścieżka
plików szablonów jest do nich przekazywana, często jednak dobrym pomysłem jest stworzenie
wirtualnej nazwy typu template do wypróbowania szablonów z przeglądarki bez
pisania żadnego kodu.
Reasumując: klasa DBAccess ułatwia uruchamianie szablonów i diagramów aktualizujących
(bezpośrednich ciągów znaków lub plików) i zwraca wyniki jako ciąg znaków XML, na
którym można zastosować arkusz stylów (stylesheet) i wysłać przekształcone w HTML
do klienta.
Utility.vb
Klasa Utility zawiera metody stosowania arkuszy stylów XSLT i rozwiązywania wyrażeń
XPath. Dla przykładu pokazano metodę ApplyXSL klasy Utility:
Public Function ApplyXSL(ByVal XMLText As String, _
ByVal XSLFileName As String) As String
Try
Dim XSLTObj As New XslTransform()
XSLTObj.Load(XSLFileName)
Dim StringReaderObj As New StringReader(XMLText)
Dim SourceXMLDoc As New XPathDocument(StringReaderObj)
Dim StringWriterObj As StringWriter = New StringWriter()
XSLTObj.Transform(SourceXMLDoc, Nothing, StringWriterObj)
Return StringWriterObj.ToString()
Catch e As Exception
ErrorHandler.Log(e.ToString())
End Try
End Function
W tej aplikacji klasa DBAccess jest użyta do wywołania szablonu SqlXml, który
zwraca ciąg znaków XML jako wynik uruchomienia szablonu. Plik arkusza stylów XSLT
jest następnie użyty do przekształcenia ciągu znaków XML w kod HTML. Dla tej konwersji
została użyta metoda ApplyXSL. Ta metoda pobiera dwa parametry − ciąg znaków
XML i nazwę pliku XSLT. Zwraca przekształcony tekst, który można następnie przesłać
do klienta, używając metody Response.Write w kodzie pliku .aspx.
Ta metoda używa instancji klasy XslTransform do wczytania arkusza stylów i klasy
XpathDocument do wczytania źródłowego ciągu znaków XML. Wywołanie metody Transform
zwraca obiekt StringWriter zawierający przekształcony tekst, który następnie
jest zwracany do wywołującego jako ciąg znaków.
Metoda ApplyXSL jest przeciążana w celu pobrania parametrów XSLT na wejściu
i przekazania tych parametrów do arkusza stylów XSLT. Dodatkowy parametr dla
ApplyXSL jest przekazany ponownie jako kolekcja HashTable, która zawiera
pary: nazwa-wartość parametrów XSLT. Oto dodatkowy kod w przeciążonej metodzie
ApplyXSL:
Dim XSLParams As New XsltArgumentList()
Dim ParamEnum As IDictionaryEnumerator = Params.GetEnumerator()
While ParamEnum.MoveNext()
XSLParams.AddParam(ParamEnum.Key, "", ParamEnum.Value)
End While
XSLTObj.Transform(SourceXMLDoc, XSLParams, StringWriterObj)
Aby zbudować listę parametrów która ma być przekazana do arkusza styli XSLT,
należy użyć klasy XsltArgumentList. Instancja XsltArgumentList jest przekazywana
do metody Transform, która następnie przekazuje listę parametrów do arkusza
stylów.
Następną użyteczną funkcją klasy Utility jest EvalXPathExpr która pozwala
na zapytanie o pojedynczy węzeł XML i odczytanie jego wartości. Ta metoda pobiera
źródłowy tekst XML na wejściu oraz wyrażenie XPath i zwraca albo wartość węzła,
jeżeli zostanie znaleziona, albo pusty ciąg znaków.
Public Function EvalXPathExpr(ByVal XMLText As String, ByVal XPathExpr As String) As String
Try
Dim StringReaderObj As New StringReader(XMLText)
Dim SourceXMLDoc As New XPathDocument(StringReaderObj)
Dim XPathNavObj As XPathNavigator = SourceXMLDoc.CreateNavigator()
Dim ResultNodes As XPathNodeIterator
ResultNodes = XPathNavObj.Evaluate(XPathExpr)
Dim ReturnValue As String
If ResultNodes.Count = 1 Then
ResultNodes.MoveNext()
ReturnValue = ResultNodes.Current.Value.ToString()
Return ReturnValue
Else
Return ""
End If
Catch e As Exception
ErrorHandler.Log(e.Message)
Return ""
End Try
End Function
Poprzednia metoda używa klas StringReader i XPathDocument do wczytania źródłowego
ciągu znaków XML. Następnie XPathNavigator jest stworzony dla obiektu XPathDocument.
Potem metoda Evaluate klasy XPathNavigator jest wykonywana do przekazania
wyrażenia XPath. Funkcja EvalXPathExpr używa wejściowego wyrażenia XPath
do wybrania pojedynczego pasującego węzła. Jeśli został znaleziony pasujący węzeł
XML, zwracana jest jego wartość.
Jeżeli zostało znalezionych więcej pasujących węzłów lub nie znaleziono żadnego,
zwracany jest pusty ciąg znaków.
Aplikacja ASP.NET
Projekt TrackWeb jest aplikacją WWW ASP.NET, która została napisana za pomocą
języka Visual Basic .NET. Zawiera formularze WWW i ich pliki, kod obsługujący stronę
ASPX, arkusze stylów XSLT, plik Web.config, rysunki oraz podfoldery. Formularze
WWW są używane do prezentacji list projektów i zadań, do dodania nowego projektu
lub zadania, do aktualizacji istniejącego projektu lub zadania i do ustawienia preferencji
użytkownika. W następnym dziale zostanie omówione użycie Components.dll do wywołania
istniejących plików szablonów, dynamicznych szablonów, diagramów aktualizujących
i zastosowania arkuszy stylów XSLT.
Default.aspx
Przede wszystkim należy uruchomić pierwszą stronę default.aspx i znaleźć metodę
Page_Load. (Z uwagi na skróty niektóre linie kodów zostały pominięte; trzeba
więc przejrzeć pliki źródłowe, by zobaczyć pełne kody).
Imports Projects.Components
...
CookieVal = Request.Cookies("ProjTrack_EmpID").Value()
'If cookie not found, redirect to firstvisit.aspx (code ommited here)
'If cookie found:
Dim EmpObj As New tblEmployees()
Dim UtilityObj As New Utility()
Dim CurrentViewVal As String
CurrentViewVal = UtilityObj.EvalXPathExpr( _
EmpObj.GetEmpPrefs(CookieVal), _
"//tblEmpPreferences/@InitialView")
If CurrentViewVal = "1" Then
Response.Redirect("taskslist.aspx")
Else
Response.Redirect("projectslist.aspx")
End If
Poprzedzający kod sprawdza wartość ProjTrack_EmpID w pliku cookie (znacznik
stanu klienta). Jeżeli wartość nie zostanie znaleziona, strona jest przekierowana
do firstvisit.aspx. Jeśli wartość pliku cookie zostanie znaleziona, klasa
tblEmployees zostanie użyta do odczytania ustawień pracownika przez wywołanie metody
GetEmpPrefs. Metoda GetEmpPrefs wewnętrznie używa klasy DBAccess i
szablonu GetEmpPrefs.xml − zwraca ona preferencje pracownika w ciągu znaków XML
w celu ustalenia, czy przekierować pracownika do okna Projects, czy Tasks,
a decyzja ta bazuje na kolumnie InitialView w tablicy tblEmpPreferences.
Następnym krokiem jest przekazanie preferencje pracownika w ciągu znaków XML
i wyrażenie XPath //tblEmpPreferences/@InitialView do funkcji EvalXPathExpr. Na
podstawie wartości zwróconej przez tę funkcję, kontrola jest przekazywana do okna
Projects albo Tasks.
Formularz WWW firstvisit.aspx (Rysunek 6) przyjmuje adres e-mail i, jeżeli formularz
zostaje wysłany, używa metody GetEmpIdFromEmail klasy tblEmployees,a następnie
ustawia zwrócony EmpID w pliku cookie w komputerze pracownika.
Projectslists.aspx
Formularz WWW projectslist.aspx (rysunek 7) pokazuje listę projektów, które są
posortowane stosownie do preferencji pracownika. Możliwe jest filtrowanie listy
w polach: Właściciel (Owner), Wydział (Department),
Priorytet (Priority) lub Status (Status). Strona .aspx
zawiera standartowy tekst HTML i wywołuje metodę BuildProjectList kodu ukrytego
z pliku projectslist.aspx.vb. Oto jak wygląda metoda Page_Load w pliku projectslist.aspx.vb:
Try
EmpID = Request.Cookies("ProjTrack_EmpID").Value()
Catch
Response.Redirect("firstvisit.aspx")
End Try
If (IsPostBack) Then
UpdateFilterSettings()
End If
Poprzedzający kod w pierwszej kolejności sprawdza, czy pole ProjTrack_EmpID w
pliku cookie jest obecne; jeżeli nie −przekierowuje do strony firstvisit.aspx.
Tabela tblEmpPreferences zawiera dwa pola (ProjFilterCriteria i
TaskFilterCriteria), używane do przechowywania kryterium filtrowania Projektów
(Projects) i Zadań (Tasks) na podstawie formatu:
<Filter>
<FilterStatus>2</FilterStatus>
<FilterDepartment>1</FilterDepartment>
<FilterOwner>2</FilterOwner>
<FilterPriority></FilterPriority>
</Filter>
Jeżeli pracownik wybierze pozycje z pola wyboru filtru w dolnej części zakładki
Projektów lub Zadań i następnie kliknie Zastosuj Filtr (Apply
Filter), metoda Page_Load w projectlist.aspx.vb wywoła lokalną metodę
UpdateFilterSettings. Ta lokalna metoda stworzy ciąg znaków z diagramem aktualizującym,
użyje klasy DBAccess do wykonania diagramu aktualizującego i zmodyfikuje (doda lub
zmieni) rekord w tabeli tblEmpPreferences.
Private Sub UpdateFilterSettings()
Dim UpdgStr As String
Dim BeforeBlockStr As String
Dim EmpObj As New tblEmployees()
Dim UtilObj As New Utility()
Dim Row_ID As String
Row_ID = UtilObj.EvalXPathExpr(EmpObj.GetEmpPrefs(EmpID), _
"//tblEmpPreferences/@Row_ID")
If Row_ID.Length > 0 Then
BeforeBlockStr = "<updg:before><tblEmpPreferences Row_ID='" & _
Row_ID & "'/></updg:before>"
End If
UpdgStr = _
"<ROOT xmlns:updg='urn:schemas-microsoft-com:xml-updategram'>" & _
"<updg:sync >" & _
BeforeBlockStr & _
"<updg:after> <tblEmpPreferences " & _
"EmpID='" & EmpID & "' ProjFilterCriteria='<Filter>" & _
"<FilterPriority>" & _
Request.Form("PriorityCodes") & "</FilterPriority>" & _
"<FilterStatus>" & _
Request.Form("StatusCodes") & "</FilterStatus>" & _
"<FilterDepartment>" & _
Request.Form("Departments") & "</FilterDepartment>" & _
"<FilterOwner>" & _
Request.Form("Employees") & "</FilterOwner>" & _
"</Filter>' " & _
"/>" & _
"</updg:after>" & _
"</updg:sync>" & _
"</ROOT>"
Dim DBAccObj As New DBAcess()
DBAccObj.ExecuteTemplate(UpdgStr)
End Sub
Poprzedzająca funkcja dynamicznie tworzy ciąg znaków z diagramem aktualizującym
i używa klasy DBAccess do wykonania diagramu do dodania lub zmiany rekordu z preferencjami
użytkownika w tabeli tblEmpPreferences. Kod naświetla sposób dynamicznego
tworzenia diagramu aktualizującego i jego wykonanie. Alternatywą budowania ciągu
znaków diagramu aktualizacji jest użycie klasy StringBuilder do zamiany kosztownego
łączenia ciągu znaków lub użycie zewnętrznego pliku diagramu aktualizacji i przekazanie
do niego parametrów.
Metoda UpdateFilterSettings przede wszystkim używa metod tblEmployees.GetEmpPrefs
i Utility.EvalXPathExpr do znalezienia rekordu z preferencjami pracownika.
Jeżeli rekord istnieje, metoda tworzy blok, który jest używany do
budowania ciągu znaków z diagramem aktualizacji. Bloki <updg:before /> i <updg:after />
służą bardziej operacji do aktualizacji niż do operacji dodawania.
W tym przypadku kosztowne operacje łączenia ciągów znaków mogą być zastąpione
przez dwa zewnętrzne pliki diagramów aktualizacji. Przekazywanie parametrów może
zostać użyte do dodawania lub zmiany rekordów w tabeli tblEmpPreferences,
jednak w pewnych sytuacjach jedyną wykonywalną opcją jest zbudowanie szablonu lub
diagramu aktualizacji dynamicznie. Przykładem jest zwrócenie listy projektów na
podstawie warunków filtrowania i sortowania. Komenda SELECT języka Transact-SQL
do wykonania, nie jest znana przed uruchomieniem, ponieważ nie jest możliwe, by
w pliku szablonu XML było dynamicznie modyfikowane zapytanie SQL. Pozostaje więc
dynamiczne zbudowanie ciągu znaków szablonu i wykonanie go.
Do zbudowania listy projektów bazujących na wybranych opcjach filtrowania strona
projectslist.aspx wywołuje metodę BuildProjectList, obecną w pliku projectslist.aspx.vb
ze ukrytym kodem. Metoda BuildProjectList na początku pobiera preferencje
pracownika na podstawie wyszczególnionych preferencji, a następnie dynamicznie buduje
ciąg znaków szablonu XML przy użyciu funkcji GetProjListTemplate, uruchamia
ten szablon XML, który zwraca wynikowe dane jako ciąg XML, i stosuje arkusz stylów
na zwróconym XML. (Kod został obcięty ze względu na czytelność; należy zajrzeć do
kodów źródłowych, by zobaczyć kompletne kody).
Dim EmpObj As New tblEmployees()
Dim DBAccObj As New DBAcess()
Dim EmpPrefs As String
EmpPrefs = EmpObj.GetEmpPrefs(EmpID)
InitializeFilterMemberVars(EmpPrefs)
With Response
.Write("<table border='0' cellPadding='3' cellSpacing='1'>")
.Write("<tr class='tablehead'>")
.Write("<td valign='top' ><b>Title</b></td>")
...
.Write(UtilObj.ApplyXSL(DBAccObj.ExecuteTemplate( _
GetProjListTemplate(EmpPrefs)), _
Server.MapPath("Style/ProjList.xsl")))
...
.Write("<td valign='top' >" & _
UtilObj.StatusCodesComboBox(FilterStatus, _
Server.MapPath("Style/CBStatusCodes.xsl"), True) & "</td>")
...
End With
Metoda BuildProjectList tworzy listę Projektów stosownie do preferencji
pracownika. Metoda zaczyna od wywołania metody tblEmployees.GetEmpPrefs,
która zwraca ustawienia jako łańcuch znaków XML. Ten ciąg znaków jest przekazywany
do funkcji składowej, nazwanej InitializeFilterMemberVars, która używa wyrażeń
XPath i metody Utility.EvalXPathExpr do przetwarzania i odczytania ustawień
filtra (tak samo jak ustawienia filtra są zapisane jako łańcuch znaków XML w polu
ProjFilterCriteria w tabeli tblEmpPreferences).
Ważną linią w kodzie jest wywołanie funkcji składowej GetProjListTemplate,
która zwraca szablon XML. Zawiera on dynamicznie utworzone zapytanie SELECT w języku
Transact-SQL, bazujące na ustawieniach filtra i sortowania. Ciąg znaków szablonu
XML zwrócony przez GetProjListTemplate przekazywany jest metodzie DBAccess
ExecuteTemplate, która zwraca wyniki zapytania SELECT jako łańcuch znaków XML.
Ostatecznie te wyniki przekazywane są do metody ApplyXSL, która generuje
tekst HTML prezentujący szczegóły projektu.
Na koniec BuildProjectList wywołuje funkcje Utility do budowania pola
wyboru filtra, które są położone w dolnej części zakładek Projects i Tasks.
Pierwszy parametr dla tych wywołań jest indeksem wybranej pozycji w polu wyboru,
drugim parametrem jest plik XSLT. Trzeci parametr jest opcjonalnym parametrem domyślnie
ustawionym jest na False, który wskazuje, że tylko rekordy z poszczególnych tabel
w wybranych polach będą wyświetlone. W metodzie BuildProjectList należy przekazać
parametr jako True, co oznacza, że w polu wyboru zostanie dodana ekstrapozycja "−Any−",
którą filtr może zostać usunięty.
Kod w taskslist.aspx.vb jest podobny do projectslists.aspx.vb.
Newproject.aspx
Jak była o tym mowa w poprzednich działach, lepiej wywoływać zewnętrzne szablony
lub pliki diagramów aktualizujących i przekazywać do nich parametry, niż używać
kosztownych połączeń łańcuchów znaków do budowania szablonów lub diagramów aktualizujących.
Plik Newproject.aspx file (rysunek 8) jest znów formularzem WWW, który pozwala na
dodanie nowego rekordu projektu w tabeli tblProjects.
Metoda Form_Load w pliku newproject.aspx.vb sprawdza, czy formularz został
wysłany (właściwość IsPostBack jest ustawiona true). Wykonuje ona
funkcję członkowską AddNewProject, która wygląda następująco:
Private Sub AddNewProject()
Dim ProjObj As New tblProjects()
Dim DataValues As New Hashtable()
With DataValues
.Add("@Title", Title.Text)
.Add("@Description", Description.Text)
If Convert.ToInt32(PercentComplete.Text) >= 100 Then
.Add("@PercentComplete", "100")
Else
.Add("@PercentComplete", PercentComplete.Text)
End If
If Request.Form("Employees") = "" Then
.Add("@Owner", "1")
Else
.Add("@Owner", Request.Form("Employees"))
End If
.Add("@StartDate", Request.Form("StartDate"))
.Add("@DueDate", Request.Form("DueDate"))
.Add("@StatusCode", Request.Form("StatusCodes"))
.Add("@DeptCode", Request.Form("Departments"))
.Add("@PriorityCode", Request.Form("PriorityCodes"))
.Add("@CreatedBy", Request.Form("CreatedBy"))
End With
ProjObj.InsertProject(DataValues)
End Sub
Poprzedzająca metoda tworzy instancję klasy HashTable i dodaje pary: nazwa–wartość
dla każdego pola w formularzu WWW, następnie przekazuje ten obiekt HashTable
do metody InsertProject klasy tblProjects. Metoda InsertProject używa
metody ExecuteTemplateFile klasy DBAccess, przesyłając InsertProject.xml
jako nazwę szablonu (plik diagramu aktualizującego) i kolekcję parametrów jako drugi
parametr. Oto jak wygląda plik InsertProject.xml diagramu aktualizującego:
<ROOT xmlns:updg="urn:schemas-microsoft-com:xml-updategram">
<!-- Add (Insert) a project -->
<updg:header>
<updg:param name="Title"></updg:param>
<updg:param name="Description"></updg:param>
<updg:param name="CreatedBy"></updg:param>
<updg:param name="Owner"></updg:param>
<updg:param name="StartDate"></updg:param>
<updg:param name="DueDate"></updg:param>
<updg:param name="StatusCode"></updg:param>
<updg:param name="DeptCode"></updg:param>
<updg:param name="PriorityCode"></updg:param>
<updg:param name="PercentComplete"></updg:param>
</updg:header>
<updg:sync >
<updg:after updg:returnid="Row_ID">
<tblProjects updg:at-identity="Row_ID"
Title="$Title"
Description="$Description"
Owner="$Owner"
PercentComplete="$PercentComplete"
StartDate="$StartDate"
DueDate="$DueDate"
StatusCode="$StatusCode"
DeptCode="$DeptCode"
PriorityCode="$PriorityCode"
CreatedBy="$CreatedBy"
/>
</updg:after>
</updg:sync>
</ROOT>
Plik Newtask.aspx zawiera kod podobny do kodu w pliku Newproject.aspx. Editproject.aspx
i Edittask.aspx pliki zawierają również podobne kody i używają klas Components.dll
do wykonywania szablonów, a także stosują arkusze stylów. Warto poświęć trochę czasu
na przejrzenie kodów w tych plikach i plikach arkuszy stylów w katalogu Style.
Admin.aspx
Zakładka Admin wylicza tabele bazy danych Projects i także pozwala
menedżerowi na dodawanie, edycje i usunięcie rekordów. Do wyświetlania i rekordów
ASP.NET udostępnia rozszerzalną i elastyczną kontrolkę DataGrid.
Rysunek 14 pokazuje użycie SQLXML do uzyskania danych w formacie XML i następnie
podłączenie ich do DataGridu ASP.NET.

Rysunek 14. Podłączanie danych XML zwróconych przez SQLXML
Strona ASPX zawiera kontrolkę dataGrid, nazwaną TableListGrid, która zawiera
dwie kolumny ułatwiające edycję i usunięcie wiersza tabeli:
<asp:datagrid id="TableListGrid" runat="server" ...>
<AlternatingItemStyle BackColor="Ivory" />
<Columns>
<asp:ButtonColumn Text="Edit" CommandName="Select">
<ItemStyle ForeColor="Black"></ItemStyle>
</asp:ButtonColumn>
<asp:ButtonColumn Text="Remove" CommandName="Delete">
<ItemStyle ForeColor="Black"></ItemStyle>
</asp:ButtonColumn>
</Columns>
</asp:datagrid>
Poniżej przedstawiony jest sposób podłączenia danych XML zwróconych przez SQLXML
w poprzedniej kontrolce DataGrid:
Private Sub EmployeesList()
lblTableName.Text = "Employees"
Dim EmpObj As New tblEmployees()
ShowTableList(EmpObj.GetAllEmployeesVerbose())
End Sub
Private Sub ShowTableList(ByVal TableData As String)
Dim objStringReader As New StringReader(TableData)
Dim objDS As New DataSet()
objDS.ReadXml(objStringReader)
If objDS.Tables.Count > 0 Then
TableListGrid.DataSource = objDS
TableListGrid.DataBind()
TableListGrid.DataKeyField = "Row_ID"
TableListGrid.Visible = True
Else
TableListGrid.Visible = False
End If
End Sub
Metoda EmployeeList używa klasy tblEmployees i wykonuje jej metodę
GetAllEmployeesVerbose, która zwraca szczegóły o pracowniku jako ciąg znaków
XML.
Łańcuch znaków XML należy przekazać do metody ShowTableList, która używa
obiektu StringReader do wczytania wejściowego tekstu XML do czytnika, a następnie
stworzyć nowy obiekt DataSet i metodą ReadXml przekazać StringReader
jako parametr wejściowy. Teraz dane pracownika wczytane są do obiektu DataSet.
Następnym krokiem jest podłączenie obiektu DataSet do DataGrid poprzez użycie
właściwości DataSource metody DataBind grid-a. Inicjując DataKeyField
w ten sposób, że gdy operacje edycji i usuwania są wykonywane, otrzymujemy Row_ID
wartości kolumny i używamy jej do znalezienia rekordu do edycji lub usunięcia.
Funkcjonalność dodawania, usuwania lub zmiany na tej stronie jest używana dla
poszczególnych klas tblXXXX. Te klasy używają klasy DBAccess i wykonują pliki diagramów
aktualizacji do wywołania modyfikacji bazy danych.
Wsparcie SOAP w SQLXML 3.0
Można zmienić przechowywane procedury w metody serwisów WWW przez kilka kliknięć
myszką. To oznacza, że dowolny klient SOAP może wywołać przechowywaną procedurę
po protokole HTTP i otrzymać wynik w formacie XML.
Aplikacja Visual Basic 6.0 jest załączona w tej aplikacji, która pozwala użytkownikowi
na przeglądanie statystyk, projektów i zadań (np. liczba zadań w trakcie lub liczba
zadań, które zostały ukończone). Aplikacja Visual Basic 6.0 używa Microsoft SOAP
Toolkit 2.0 Service Pack 2 do wywołania metod serwisów WWW, które zwracają rezultaty
jako obiekt IXMLDOMNodeList. Następnie Microsoft XML Core Services (MSXML)
4.0 jest używana do przetwarzania wyników.
Przechowywane procedury
Baza danych Projects zawiera i przechowuje dwie następujące procedury:
CREATE PROCEDURE sproc_GetEmpProjStatistics
@EmailAlias AS VARCHAR(50)
AS
SELECT a.StatusCode, count(*) as CountVal
FROM
tblProjects a JOIN tblEmployees b
ON a.Owner = b.Row_ID
WHERE b.EmailAlias = @EmailAlias
GROUP BY a.StatusCode
GO
CREATE PROCEDURE sproc_GetEmpTaskStatistics
@EmailAlias AS VARCHAR(50)
AS
SELECT a.StatusCode, count(*) as CountVal
FROM
tblTasks a JOIN tblEmployees b
ON a.Owner = b.Row_ID
WHERE b.EmailAlias = @EmailAlias
GROUP BY a.StatusCode
GO
Te przechowywane procedury zwracają kod statusu i zliczają projekty lub zadania
w tej kategorii statusu.
Stworzenie wirtualnej nazwy typu soap
SQLXML 3.0 wprowadza jeszcze jeden typ wirtualnej nazwy − soap,
w uzupełnieniu do istniejących typów dbobject, template
i schema. Wirtualna nazwa z typem soap pozwala na konfigurację
przechowywanych procedur, funkcji definiowanych przez użytkownika (UDFs) lub szablonów
jako metod serwisów WWW. Proces konfiguracji generuje plik .wsdl i dodaje operacje
WSDL do każdej przechowywanej procedury, UDF lub szablonu. Konfiguracje nazw wirtualnych
z typem soap są zapisywane w pliku .ssc.
Do stworzenia nazwy wirtualnej typu soap i konfiguracji dwóch przechowywanych
procedur jako metod serwisów WWW trzeba wykonać następujące operacje:
- Uruchomić narzędzia konfiguracji SQLXML 3.0 (Configure IIS Support tool).
- Kliknąć dwa razy wirtualny catalog ProjectsSQLVirDir, stworzony wcześniej.
- W zakładce Virtual Names w polu Name wpisać ProjectsWebSvc.
- W polu Type wpisać soap.
- W polu Path wpisać C:\Projects\SQLVirDir\SQLWebSvc.
- W polu Web Service Name wpisać ProjectsWebSvc (tę samą nazwę,
jak nazwa wirtualna), jak pokazano na rysunku 15.
- Kliknąć save. Nowa wirtualna nazwa ukaże się w polu Defined
virtual names.
Rysunek 15. Tworzenie wirtualnej nazwy typu
soap
- Wybrać ProjectsWebSvc w polu Defined virtual names i kliknąć Configure.
- Kliknąć przycisk SP/Template (…), i wybrać procedurę sproc_GetEmpProjStatistics
z listy przechowywanych procedur.
- W oknie dialogowym SOAP stored procedure mapping kliknąć OK.
- W oknie dialogowym SOAP virtual name configuration (rysunek 16), kliknąć
Save.

Rysunek 16. Konfigurowanie wirtualnej nazwy
soap
Teraz należy powtórzyć poprzednie kroki, by wskazać przechowywaną procedurę
sproc_GetEmpTaskStatistics. W oknie dialogowym Soap virtual name configuration
obie nazwy przechowywanych procedur powinny być pokazane w polu Methods,
jak pokazano na rysunku 17.

Rysunek 17. Procedury wbudowane udostępnione jako metody SOAP
- Kliknąć OK.
- Następnie w oknie dialogowym Virtual Directory Manager kliknąć OK ponownie.
Konfiguracja stworzyła pliki .wsdl i .ssc. Plik .wsdl opisuje serwis i operacje,
jakie będą używane z aplikacji klienckiej SOAP Toolkit. Plik .ssc jest zarządzany
przez SqlXml; zawiera informację konfigurującą wirtualną nazwę typu soap.
Klient Visual Basic 6.0
Przechowywana procedura sproc_GetEmpProjStatistics i sproc_GetEmpTaskStatistics
są teraz dostępne jako metody SOAP. Można użyć Microsoft SOAP Toolkit do wywołania
tych przechowywanych procedur (jako metody serwisu WWW) i przetwarzać zwrócone dane
XML.
Aplikacja kliencka w Visual Basic 6.0, która została dostarczona z przykładową
aplikacją, jest aplikacją typu tray icon. Po uruchomieniu aplikacji Visual Basic
można zobaczyć okno dialogowe Projects/Tasks Tracking System Client i ikonę
w pasku powiadomień (tray icon). Aby zakończyć – trzeba kliknąć prawym przyciskiem ikonę, a następnie wybrać Exit.)

Rysunek 18. Klient w Visual Basic 6.0
Ta aplikacja odwołuje się do plików dll Microsoft SOAP Toolkit 2.0, Service Pack
2 Microsoft XML, Core Services (MSXML 4.0). Po skompilowaniu i przetestowaniu aplikacji
klienckiej należy zapamiętać, by zaktualizować stałą WSDL URL w górze kodów:
Option Explicit
Const SQLXMLWebSvsWSDLURL = "http://sch02singhdnt/ProjectsSQLVirDir/ProjectsWebSvc?wsdl"
Kliknięcie Go w oknie dialogowym Projects/Tasks Tracking System Client
wywoła metodę GetProjectAndTaskStatistics, która aktualnie inicjuje wywołanie
SOAP i przetwarza odpowiedź.
Private Sub cmdGo_Click()
GetProjectAndTaskStatistics
End Sub
Metoda GetProjectAndTaskStatistics rozpoczyna się deklaracją instancji
klasy SoapClient z biblioteki narzędziowej SOAP i zmiennej typu IXMLDOMNodeList
z biblioteki MSXML 4.0:
Private Sub GetProjectAndTaskStatistics()
Dim retVal As Integer
Dim objClient As New SoapClient
Dim retNodeList As IXMLDOMNodeList
Me.MousePointer = vbHourglass
InitializeControls
Metoda InitializeControls zeruje etykiety rezultatów do "---", a następnie
wywołuje metody mssoapinit i przesyła do nich adres WSDL URL. Wywołanie mssoapinit
inicjuje obiekt SoapClient przez użycie pliku WSDL, tak że wszystkie operacje
identyfikowane przez serwis mogą być dostępne przez użycie obiektu SoapClient.
objClient.mssoapinit SQLXMLWebSvsWSDLURL
Teraz można wywoływać metody serwisu WWW, a przede wszystkim metodę do pobrania
statystyk projektów:
On Error Resume Next
Set retNodeList = objClient.sproc_GetEmpProjStatistics( _
txtEmailAlias.Text, retVal)
With retNodeList.Item(0)
lblCompleted.Caption = _
.selectSingleNode("//row[@StatusCode='3']").Attributes(1)
.nodeTypedValue
lblInProgress.Caption = _
.selectSingleNode("//row[@StatusCode='2']").Attributes(1)
.nodeTypedValue
lblNotStarted.Caption = _
.selectSingleNode("//row[@StatusCode='1']").Attributes(1)
.nodeTypedValue
lblOngoing.Caption = _
.selectSingleNode("//row[@StatusCode='5']").Attributes(1)
.nodeTypedValue
End With
Kod pokazany powyżej wywołuje metodę sproc_GetEmpProjStatistics serwisu
WWW i przekazuje do niej adres e-mail jako pierwszy parametr oraz liczbę typu integer,
która zawiera zwrócony kod. Metoda sproc_GetEmpProjStatistics serwisu WWW
zwraca obiekt IXMLDOMNodeList, zawierający wynik XML podobny do następującego:
<sqlresultstream:SqlXml
xmlns:sqlresultstream="http://schemas.microsoft.com/SQLServer/2001/12/SOAP/types/SqlResultStream"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="sqltypes:SqlXml"
xmlns:sqltypes="http://schemas.microsoft.com/SQLServer/2001/12/SOAP/types"
sqltypes:IsNested="false">
<SqlXml>
<row StatusCode="3" CountVal="1"/>
<row StatusCode="2" CountVal="3"/>
</SqlXml>
Następnie należy użyć metody selectSingleNode, wyrażenia XPath i kolekcji
Atrybutów do pobrania liczb dla rozmaitych kodów statusu, to samo − dla statystyk
zadań. Teraz należy wywołać metodę sproc_GetEmpTaskStatistics serwisu WWW,
wyrażenia XPath i kolekcję Atrybutów do pobrania liczb dla rozmaitych kodów
statusu.
Zakończenie
XML i wsparcie Microsoft.NET Framework w serwerze SQL Server 2000 może uprościć
proces tworzenia aplikacji. W uzupełnieniu, aplikacje budowane przy użyciu SQL Server
2000, XML i Visual Basic .NET mogą być zmienione w serwisy WWW, które następnie
mogę być dostępne z dowolnej platformy i dowolnego języka. W ostatnim przykładzie
pokazano nawet w jaki sposób można skorzystać z tych możliwości za pomocą kodu w
Visual Basic 6.0 dzięki użyciu Microsoft SOAP Toolkit.
Spis treści
Pobierz pełny kod przykładu: ProjTrackSystemCode.zip