24 Bazy danych i widok record


Rozdział 24
Bazy danych i widok Record
Konfigurowanie źródła danych ODBC Łączenie z bazą
danych w aplikacjach MFC
Otwieranie zbiorów rekordów i odczytywanie rekordów Dodawanie,
usuwanie i edytowanie rekordów bazy danych
Tworzenie projektu opartego na widoku Record
Bazy danych
Duże firmy gromadzą każdego dnia swojej działalności olbrzymie ilości danych. Prze-
chowują dane o klientach i dostawcach, wielkości sprzedaży, zapasach magazynowych i wiele
innych informacji. Większość firm przechowuje te informacje w bazach danych, a ściślej w
tzw. DMS-ach (ang. database managment system, system zarządzania bazami danych). DMS
jest to taki program, który przechowuje dane w wysoko shierarchizowanej strukturze i
dostarcza narzędzi do sprawnego odczytywania i uaktualniania danych.
Istnieją dwa podstawowe typy baz danych: relacyjne bazy danych (ang. relational
databases) i obiektowe bazy danych (ang. object databases). Różnica między nimi leży w
sposobie, w jaki obsługują dane. Relacyjne bazy danych ograniczają się do rozpoznawania
prostych typów danych (znaków, łańcuchów, liczb całkowitych itp.) i nie pozwalają na
tworzenie nowych typów danych. Obiektowe bazy danych pracują na wyższym poziomie:
pozwalają na tworzenie definiowanych przez użytkownika typów danych. Obiekty danych są
w tym przypadku odbiciem obiektów wykorzystywanych w programowaniu obiektowym.
Przykładowo, obiekt przechowywany w bazie danych może być człowiekiem lub pojazdem
(zamiast np. łańcuchem). Niniejszy rozdział koncentruje się na relacyjnych bazach danych,
ponieważ istnieją dłużej i są szerzej używane niż obiektowe bazy danych.


634 Poznaj Yisuał C++ 6
Relacyjne bazy danych
Przed pojawieniem się komercyjnych baz danych aplikacje obsługujące przechowywanie
danych tworzone były w oparciu o struktury plikowe. Tylko twórca programu tak naprawdę
wiedział, w jaki sposób dane są zorganizowane. Oznaczało to, że jeśli użytkownik programu
potrzebował niestandardowych, przystosowanych do jego potrzeb operacji na
przechowywanych w bazie danych, konieczne było (zazwyczaj kosztowne i czasochłonne)
przebudowanie programu.
Relacyjne bazy danych usunęły większość tych problemów standaryzując projektowanie
systemów przechowujących dane. Dane w relacyjnych bazach danych organizowane są
tablicach, kolumnach i rzędach (ang. tables, columns, rows). Typowa baza danych może na
przykład posiadać tablicę Klienci z kolumnami zatytułowanymi Nazwisko i Numer telefonu.
Każdy z rzędów tablicy odpowiadać będzie jednemu klientowi. Przykładowo, jeden rząd może
być zatytułowany MIKOM, a kolejny Microsoft. Układ tablic i kolumn przechowywany jest w
schemacie bazy danych (ang. database schemd). Schemat ten definiuje typ danych każdej
kolumny i wzajemne zależności między tablicami.
ODBC
Relacyjną bazę danych możemy zakupić od wielu różnych dostawców. Każda baza danych
ma swoją specyficzną strukturę i własny zestaw odwołań do funkcji API. Jeśli chcielibyśmy
pisać uniwersalną współdziałającą z różnymi bazami danych aplikację, musielibyśmy ogromną
ilość czasu i energii poświęcić na zaznajomienie się nawet z kilkoma najbardziej
podstawowymi bazami danych. Poza tym aplikacje z zasady nie powinny ograniczać się tylko
do obsługi wybranych baz danych, ale współdziałać ze wszystkimi. Aby możliwe było pisanie
aplikacji współpracujących z każdą bazą danych dowolnego producenta oprogramowania,
potrzebna jest wspólna dla wszystkich baz danych metoda programowania. Taka metoda
istnieje i nazywa się ODBC (od ang. Open Database Con-nectivity).
Rozprowadzanie aplikacji ODBC
Do aplikacji opartej na ODBC (jeśli zamierzamy ją sprzedawać) należy dołączyć kilka
dodatkowych plików. Pliki te można znaleźć w katalogu OS\System na CD-ROM-ie Visual
C++. Więcej informacji na ten temat zawiera znajdujący się w tym katalogu plik
REDISTRB.WRI.
ODBC zapewnia wspólny interfejs programowania dla różnych odmian relacyjnych baz
danych. Aby to było możliwe, musi istnieć narzędzie pośredniczące, które interpretować
będzie standardowe odwołania do funkcji ODBC na odwołania specyficzne dla określonej
bazy danych. Narzędziem takim jest sterownik ODBC dostarczany przez twórcę bazy danych
lub inną firmę specjalizującą się w dostarczaniu oprogramowania zabezpieczającego
kompatybilność programów. ODBC jest obecnie powszechnie uznawanym standardem


Bazy danych i widok Record 635
i sterowniki ODBC są dostępne dla wszystkich najważniejszych istniejących na rynku baz danych.
Programując aplikację należy zainstalować sterownik ODBC dla bazy danych, z której będziemy
korzystać podczas tworzenia programu. Najbardziej rozpowszechnione sterowniki ODBC Microsoftu
można zainstalować w oparciu o aplikacje takie jak Office czy Visual Studio. Aby korzystać z innych
baz danych, należy poprosić sprzedawcę konkretnej bazy o dostarczenie odpowiedniego sterownika
ODBC. Rysunek 24.1 pokazuje, w jaki sposób sterownik ODBC łączy bazę danych z programowaną
przez nas aplikacją.
Baza
danych
ABC



Sterownik ABC
ODBC





Administrator
ODBC



Aplikacja
DB.exe





Baza
danych
XYZ



Sterownik XYZ
ODBC





Rysunek 24.1. Łączenie aplikacji z bazą danych w standardzie ODBC
Polecenia są kierowane do sterownika ODBC, a następnie przesyłane do bazy danych za pomocą
języka SOŁ (od ang. Structured Query Language). Język ten został stworzony specjalnie do obsługi
komunikacji z bazami danych i jest obecnie powszechnie akceptowanym standardem. Odmian języka
SOŁ jest praktycznie tyle, ile jest firm sprzedających bazy danych, przy czym każda firma dodaje tu
własne modyfikacje. Istnieje pewien minimalny zestaw wymagań gwarantujący, że sterownik ODBC
obsługiwać będzie pewien zestaw podstawowych poleceń. Nadal jednak sterownik będzie mógł
obsługiwć polecenia niestandardowe, ponieważ ODBC pozwala na bezpośrednie wykonywanie instrukcji
języka SOŁ. Niemniej dołączenie do aplikacji nietypowych instrukcji może spowodować, że aplikacja
utraci zdolność współpracy z innymi bazami danych, a to przecież jest największą zaletą ODBC.
Język SOŁ definiuje trzy typy poleceń: DDL, DML i DCL. Polecenia DDL (od ang. Data Definition
Language) służą do tworzenia i modyfikowania schematu bazy danych. Przykładowe instrukcje DDL to
CREATE DATABASE i CREATE TABLE. Polecenia DML (od ang. Data Manipulation Language) są
wykorzystywane w zapytaniach (ang. ąuery) i do manipulowania zapisanymi w bazie wartościami.
Cztery najważniejsze instrukcje DML to SELECT, INSERT, UPDATE i DELETE. Każdej instrukcji przesyłane
są parametry definiujące, której kolumny (lub kolumn) i tablicy (lub tablic) dotyczy określona instrukcja.
Polecenia DCL (od ang. Data Control Language) są wykorzystywane do przydzielania określonym
użytkownikom szerszych lub węższych praw dostępu do zawartości bazy.


636 Poznaj Visual C++ 6
Konfigurowanie źródła danych
Pierwszym zadaniem przy korzystaniu z ODBC jest skonfigurowanie źródła danych (ang. sówce). Źródło danych informuje program, gdzie umieścić fizyczne pliki bazy danych i który sterownik
ODBC jest wykorzystywany do tłumaczenia odwołań do funkcji API. Konfigurowanie źródeł danych
odbywa się za pomocą dostępnego w Panelu sterowania systemu Windows programu ODBC Data Source
Administrator.
Program ODBC Administrator
Ikonę apletu ODBC można znaleźć w Panelu sterowania. Z dwóch dostępnych ikon należy wybrać tę z
cyfrą 32 przeznaczoną do konfigurowania połączeń z 32-bitowymi bazami danych. Drugi aplet służy
do połączeń z 16-bitowymi bazami danych.
Aby skonfigurować źródło danych, które będzie wykorzystywane w przedstawionej w tym rozdziale
przykładowej aplikacji, należy wykonać czynności opisane w algorytmie "Tworzenie i konfigurowanie
źródła danych ODBC" poniżej. Budowana tutaj przykładowa aplikacja korzysta z pliku stdreg32.mdb,
który jest bazą Accessa dostarczaną na CD-ROM-ie Visual C++ jako przykład bazy danych. Niestety nie
możemy podać dokładnej lokalizacji tego pliku na CD-ROM-ie, bowiem zmienia się ona w zależności od
wersji kompilatora. Należy odnaleźć go samodzielnie i przekopiować na twardy dysk. Niemniej dla
potrzeb przedstawionej niżej procedury założymy, że znajduje się on w katalogu C^Databases.
Tworzenie i konfigurowanie źródła danych ODBC
1. W menu Start systemu Windows kliknij menu Settings, następnie wybierz Control Panel.
2. Kliknij dwukrotnie (lub zaznacz i wciśnij Enter) ikonę podpisaną 32bit ODBC. Pojawi się
przedstawione na rysunku 24.2 okno dialogowe ODBC Data Source Administrator.
eaODBC Dala Samce Adminiftiatoi
UBB] DSM j System OSN j File DSN | Driwis | Tradng | Connectial Poolng | About j


ilw Dala Sources
YBu.al Foh-Pro
Tables
ticto;oHVj;uai FoKFro
Diivei
Micro3oftVisuatFoxPfoDr
ivef
W.
Refnoye
Configme.,



AnODBC Usef data soufce stofes infotmation abouthow
toconnect to the indcaled data pfoyider A User data souice is
oni^ '/islble to you. and can oniy be used on the cunent
machirne.
Cancel Htlp
Rysunek 24.2. Okno dialogowe ODBC Data Source Administrator


Bazy danych i widok Record 637





3.
Wybierz User DSN i kliknij przycisk Add. Pojawi się przedstawione na rysunku 24.4 okno
dialogowe Create New Data Source. Możemy zmienić ustawienia bieżącego źródła danych
wybierając je w liście User Data Sources i klikając Cpnfigure.
Cieate New Data Sówce


Setect a dwerfoi whichrou want to set upa data source,
Micro^olt dBa^e Dnvef
C.dbf] Miciosott Fo^Pto
Dnvef ['.dbfj Miaosolt
ODBC fo] Oracie
Microsoft VBual FouPro
Driver SOŁ Servel
! 3.51,102900
3,51 102900
3.51.102900
2.573.252309
6.00.804700
3.B0.0303
| CofnpanjJ
rosoft Cofporation
Micfosołt Colpofation
::
Microsoft Cofporation
|||l Mictosofl
Corporation 1;
Microsofl Corporation.:
Mictosoft Corpofation
||:
al



Finish Cancet
Rysunek 24.3. Okno dialogowe Create New Data Source
4. Wybierz sterownik ODBC, za pomocą którego chcesz utworzyć nowe źródto danych. Sterownik ten
musi odpowiadać typowi bazy danych. Tutaj wybieramy sterownik Microsoft Access Driver
(*.mdb). Kliknij przycisk Finish. Pojawi się przedstawione na rysunku 24.4 okno dialogowe ODBC
Microsoft Access Setup.
QOBC Micioloft Access 9? Setup


OK Cance)
Hełp
Advaficed..
Data Sówce y.dme: jStudent
regKtfation DesctiptkJn. Dalabase
Course enfolimeni and
admini;>[alion
Dałaba^e; c:\Dstabases\stdte932,mdb j
| "letecC 1| Cteate... l Be'pa"..
S^slem Database - .............
ff Nong r
Daiabe;





Rysunek 24.4. Okno dialogowe ODBC Microsoft Access Setup
6. W polu Data Source Narne wpisz nazwę źródła danych. Tutaj wpisaliśmy Student Registration
(Rejestracja studentów). Możemy wpisać dowolną nazwę, pamiętając jednak o tym, żeby nie
utworzyć dwóch źródeł o tej samej nazwie.
7. Dodatkowo w polu Description można wpisać opis źródła danych. Tutaj wpisaliśmy Course
enrollment and administration (Zaliczenia i sprawy administracyjne).
8. Kuknij przycisk Select. Pojawi się okno dialogowe Select Database.


638_____________________________________Poznaj Visual C++ 6
9. Wpisz nazwę pliku bazy danych w polu Database Name lub wybierz go z listy katalogów
Directories. Lokalizacja i nazwa wybranej bazy danych wyświetlana jest w oknie dialogowym.
10. Aby zamknąć okno dialogowe ODBC Microsoft Access Setup kliknij OK. Źródto Sudent
Registration powinno pojawić się teraz na liście User Data Sources.
11. Aby zamknąć okno dialogowe ODBC Data Souree Administrator, kliknij OK. Zamknij Panel
sterowania.
Okno przedstawione na rysunku 24.4 jest specyficzne dla bazy Access Microsoftu. Inne bazy
danych będą w tym momencie wyświetlać własne konfiguracyjne (ang. setup) okna dialogowe i
wymagać definiowania innych opcji.
Problemy z podłączeniem źródła danych
Jeśli pojawią się problemy z podłączeniem do bazy danych, można spróbować zmienić typ źródła
danych. Przykładowo, jeśli wybraliśmy User DSN i pojawią się problemy, możemy spróbować wybrać
typ System DSN.
Warto tu zauważyć, że możemy skonfigurować dwa typy źródła danych: domyślny typ DSN
użytkownika (ang. userDSN) i DSN systemu (ang. system DSN). DSN użytkownika jest dostępny tylko
dla użytkownika (administratora), który dodał dane źródło, podczas gdy DSN systemu jest dostępne dla
każdego, kto pracować będzie na danym komputerze.
Tworzenie aplikacji korzystającej z bazy danych
Sposób tworzenia aplikacji sięgającej do bazy danych zależy w znacznej mierze od kilku
podstawowych założeń, które postawimy sobie na początku pisania programu. Przykładowo, musimy
zdecydować, czy aplikacja ma sięgać do jednej, czy do kilku baz danych albo czy ma również
obsługiwać inne typy plików. Możliwe są różne konfiguracje, które wymagają rozważenia na samym
początku, ponieważ najprostszym sposobem dołączenia do aplikacji możliwości korzystania z bazy
danych jest wybranie odpowiednich opcji podczas tworzenia projektu za pomocą kreatora AppWizard.
Opcje te po wprowadzeniu za pomocą kreatora nie będą mogły już być zmienione i jedynym sposobem
ich modyfikacji będzie ręczna edycja kodu programu.
Załączanie do programu bazy danych za pomocą kreatora AppWizard
Na drugiej stronie kreatora AppWizard znajdują się cztery przełączniki, które pozwalają wybrać
różny stopień wykorzystania baz danych w programie (rysunek 24.5).


Bazy danych i widok Record 639
MFC AppWKard - Step 2 o( 6


^o'rdvi viłdo'~^~^ | What dalabase support woutó you like to
include?
tcord Vi
yiłdo
fH ii"'"'""
l (* None | f~ Header files orły l ^ Database View without file
support ^ Database wwwithfitewppoft
Ifyou include a daiabase view.>'ou must
select a daEa source.
DataSouree...
The łabie '[Sludent]' in dala louree
'StudenI fegisttation' is seiecled.
< Back Neul > Finish Cancel





Rysunek 24.5. Opcje stopnia wykorzystania baz danych w aplikacji w kreatorze AppWizard Pierwsza
opcja (None) jest oczywista. Aplikacja nie korzysta z baz danych.
Druga opcja (Header Files Oniy) dodaje do projektu dyrektywę # include załączającą plik
nagłówka zawierający definicje klas CDatabase i CRecordset. Klasy te służą do łączenia się z bazami
danych i sięgania do danych w nich zawartych.
Dodawanie baz danych do gotowego projektu
Możemy dodać możliwość korzystania z baz danych do projektu pierwotnie za pomocą kreatora
AppWizard pozbawionego tej opcji, załączając do pliku nagłówka stdafx.h dwa pliki: afxdb.h i
afxdao.h.
Trzecia (Database View Without File Support) i czwarta (Database Viev ^Vith File Support)
opcja wymagają uprzedniego zdefiniowania źródła danych dla danego projektu i w zależności od
kolejnych wybranych opcji utworzą odpowiednie klasy. Różnica pomiędzy nimi polega na tym, że druga
opcja dodaje do aplikacji automatycznie menu File.
Korzystając z kreatora AppWizard i opcji Database View Without File Support
utworzymy aplikację SDI (o nazwie UsingDB). Po wybraniu tej opcji należy wykonać poniższe
czynności.
Łączenie aplikacji ze źródtem danych za pomocą kreatora AppWizard
l. Na stronie drugiej kreatora wciśnij przełącznik Database View Without File Support, jeśli aplikacja
nie potrzebuje menu File, w przeciwnym wypadku wciśnij Database Viev With File Support.
Wybierz Database View Without File Support.
Warto zauważyć, że wybranie tej opcji automatycznie definiuje aplikację jako SDI.


640 Poznaj Visual C++ 6
2. Kliknij przycisk Data Source. Pojawi się widoczne na rysunku 24.6 okno dialogowe
Database Options.
Database Options

|?lx(

r Datasource












OK )

i cr ODBC; : r
fiAO; : C OLE
OB:
;
Recordsetłype
^ Snapshot
, Advanced
| R ,^;::i-,

c.b^.Ai'^iŁLylBltaiiaiBtJ

|

Cancel


J





C Dynaset <" ,?::i.-



Rysunek 24.6. Okno dialogowe Database Options
3. Wybierz odpowiednią opcję sposobu połączenia z bazą danych. Tutaj będzie to ODBC.
4. Z listy kombinowanej Datasource wybierz nazwę źródła danych. Tutaj Student Regi-stration. Jeśli
odpowiednia nazwa się nie pojawi, oznacza to, że należy utworzyć i skonfigurować źródło danych.
Porównaj z przedstawionym wcześniej algorytmem "Tworzenie i konfigurowanie źródła danych
ODBC".
5. Wciśnij jeden z przełączników w polu Recordset Type. Tutaj Snapshot.
6. Kliknij OK. Pojawi się przedstawione na rysunku 24.7 okno dialogowe Select Database Tables.
7. Wybierz tablicę lub tablice, dla których chcesz utworzyć zbiór rekordów. Tutaj Student.
8. Kliknij OK. Dodałeś do projektu możliwość korzystania z bazy danych. W następ
nych krokach kreatora zdefiniujesz pozostałe opcje projektu.
Zbiory rekordów typu snapshot i dynaset
Snapshot to taki zbiór rekordów, który tworzy bufory dla wszystkich pól danych i nie bierze pod
uwagę zmian wprowadzanych przez innych użytkowników.
Natomiast dynaset to zbiór rekordów, który buforuje tylko kluczowe pola i akceptuje zmiany
wprowadzone w danych przez innych użytkowników.


Bazy danych i widok Record 641
Select Dalabase Tables





Lourse
Dynabind_Section
EnrollmenT
Instructor
Section
OK
Cancel






Rysunek 24.7. Okno dialogowe Select Database Tables
Łączenie się z bazą danych
Łączenie się z bazą danych i sięganie do zawartych w niej informacji jest obsługiwane przez dwie
współpracujące ze sobą klasy: CDatabase i CRecordset. Klasa CDatabase jest odpowiedzialna za
otwieranie połączenia z bazą danych. Obiekty CDatabase można wykorzystywać w programie zarówno
do łączenia się z kilkoma różnymi bazami danych, jak i do kilkakrotnego łączenia się z tą samą bazą.
Ponieważ otwieranie połączenia z bazą danych jest dość długim procesem i bardzo obciąża zasoby
systemu, dlatego lepiej wykorzystywać ponownie połączenie już otwarte niż tworzyć nowe połączenie
dla każdego zbioru rekordów. Jeden ze sposobów na powtórne wykorzystanie połączenia polega na
osadzeniu obiektu CDatabase w klasie dokumentu, która ustanawia połączenie, a następnie utworzeniu
funkcji GetDatabase () zwracającej wskaźnik do obiektu CDatabase. Będziemy mogli teraz przesyłać
wskaźnik do obiektu CDatabase konstruktorowi obiektu CRecordset, umożliwiając w ten sposób
zbiorowi rekordów korzystanie z już istniejącego połączenia. Z bazą danych łączymy się za pomocą
funkcji CDatabase: :OpenEx. Prototyp tej funkcji przedstawiony jest na listingu 24.1.
DAO (Data Acces objects)
Alternatywnym rozwiązaniem do korzystania z klas CDatabase i CRecordset są klasy
CDaoDatabase i CDaoRecordset. Różnica między nimi polega na tym, że klasy DAO współpracują
tylko z bazami danych opartymi na mechanizmie (ang. en-gine) Microsoft Jet, podczas gdy dwie
pierwsze klasy współpracują z bazami danych sterowanymi za pośrednictwem ODBC.
Listing 24.1. LST25_1.CPP - parametry funkcji OpenEx
1 virtual BOOL OpenEx( LPCTSTR IpszConnectString,
2 DWORD dwOptions =0);


642_____________________________________Poznaj Visual C++ 6
Najczęściej funkcji przesyłany jest tylko pierwszy parametr. Zmienna ipszConnect-String jest
wskaźnikiem do łańcucha zawierającego nazwę źródła danych i dodatkowe informacje niezbędne do
połączenia się z konkretną bazą danych, takie jak nazwa użytkownika czy hasło. Źródła danych ODBC
są konfigurowane za pomocą Administratora ODBC uruchamianego za pośrednictwem odpowiedniego
apletu w Panelu sterowania. Szczegółowy opis postępowania znajduje się w przedstawionym kilka stron
wcześniej algorytmie "Tworzenie i konfigurowanie źródła danych ODBC". Parametr dwOptions jest
maską bitową (ang. bitmask) wykorzystywaną do definiowania kombinacji opcji połączeń, które
przedstawiamy w tabeli 24.1. Domyślna wartość O otworzy bazę danych z prawem do zapisu, biblioteka
kursorów ODBC nie zostanie załadowana, a okno dialogowe połączenia będzie wyświetlane tylko wtedy,
gdy łańcuch (pierwszy parametr) nie będzie zawierał wystarczającej ilości danych do zrealizowania
połączenia.
Tabela 24.1. Możliwe wartości parametru dwOptions funkcji CDatabase: : OpenEx () Wartość
Opis
OpenReadOn l y Otwiera źródło danych jako tylko do odczytu
useCursorZib Ładuje bibliotekę DLL kursorów ODBC. Biblioteka ta pokrywa część funkcji
sterownika. Przykładowo zbiory rekordów typu dynaset są niedostępne, kiedy
biblioteka kursorów jest załadowana
noOdbcDialog Blokuje wyświetlanie okna dialogowego połączeń ODBC forceOdbcDialog
Wyświetla okno dialogowe połączeń ODBC
Funkcja CDatabase: : OpenEx () może wyglądać tak jak poniżej:
CDatabase db;
db.OpenEx("ODBC;DSN=Student Registration;UID=TinyTim;PWD= CASTLE",
CDatabase::openReadOnly | CDatabase::noOdbcDialog));
Wspomnieliśmy wcześniej, że możliwe jest bezpośrednie odwoływanie się do instrukcji języka
SOŁ. Możliwość taka bywa przydatna, gdy baza danych, z którą program współpracuje, oferuje
możliwości wykraczające poza standard ODBC SQL. Do instrukcji SOŁ odwołać się można za pomocą
funkcji ExecuteSQL klasy CDatabase. Funkcja ta wymaga jako parametru wskaźnika do łańcucha
przechowującego instrukcję.
Zapytania do bazy danych
Klasa CRecordset obsługuje sięganie do danych przechowywanych w tablicach i kolumnach bazy
danych. Klasa CRecordset jest klasą abstrakcyjną (ang. abstract ciass), dlatego należy wywieść z niej
własną klasę. Za pomocą klasy CRecordset wykonujemy zapytania SQL (ang. ąuery). Wynik zapytania
jest przechowywany w buforze rekordu. Klasa CRecordset obsługuje bieżący wskaźnik rekordu (zwany
też kursorem) i umożli-


Bazy danych i widok Record_______________________________ 643
wia przeszukiwanie rekordów za pomocą jej funkcji składowych: Move, MoveNext, Move-Prev,
MoveFirst i MoveLast.
Klasa wywiedziona z klasy CRecordset przechowuje zmienne składowe dla każdej kolumny (pola)
wewnątrz zapytania. Zmiennym tym przypisywana jest bieżąca wartość reprezentowanych przez nie
kolumn za każdym razem, gdy wykonywane jest odwołanie zmieniające bieżący rekord. W przykładzie
UsingDB za pomocą kreatora AppWizard wywiedliśmy z klasy CRecordset klasę CUsingDBSet.
Definicja i kod klasy CUsingDB-Set przedstawione zostały na listingu 24.2.
Listing 24.2. LST25J2.CPP - klasa CUsingDBSet____
1 ciass CUsingDBSet : public CRecordset
2 (
3 public:
4 CUsingDBSet(CDatabase* pDatabase = NULL); O
5 DECLARE_DYNAMIC(CUsingDBSet)
6
7 // Pola/Parametry danych
S //{(AFX_FIELD(CUsingDBSet, CRecordset)
9 long m_StudentID; @
10 CString m Name; @
11 int m_GradYear; @
12 //}}AFX_FIELD @
13
14 // Funkcje przykrywające
15 // Funkcje przykrywające utworzone przez kreator AppWizard.
16 //{(AFX_VIRTUAL(CUsingDBSet)
17 public:
18 virtual CString GetDefaułtConnect() ;
19 virtual CString GetDefaultSOL();
20 virtual void DoFieldExchange(CFieldExchange* pFX) ;
21 //)}AFX_VIRTUAL
22
23 // Kod klasy
24 # i f de f _DEBUG
25 virtual void AssertValid() const;
26 virtual void Dump(CDumpContext& dc) const;
27 enndif
28 };
29 CUsingDBSet::CUsingDBSet(CDatabase* pdb)
30 : CRecordset(pdb)
31 (
32 //((AFX_FIELD_INIT(CUsingDBSet)


644_____________________________________Poznaj Visual C++ 6
33 m_StudentID =0;
34 m_Name = _T("");
35 m_GradYear =0;
36 m_nFields =3; @
37 //}}AFX_FIELD_INIT
38 m nDefaultType = snapshot;
39 }
40
41 CString CUsingDBSet::GetDefaultConnect()
42 (
43 return _T("ODBC;DSN=Student registration"); O
44 }
45
46 CString CUsingDBSet::GetDefaultSQL()
47 {
48 return _T("[Student]");
49 )
O Możemy tutaj również przesłać wskaźnik do już istniejącego obiektu CDatabase. @ Zmienne
dodane przez kreator CIassWizard do każdego pola w zbiorze rekordów.
Początkowe wartości każdego z pól w zbiorze rekordów i zmiennych m_nFields klasy CRecordset
dodane przez kreator CIassWizard.
O Funkcja Get przyzywana przez szkielet aplikacji, by dostarczyć łańcuch połączenia, gdy zbiór
rekordów jest otwierany.
Funkcja Get przyzywana w momencie otwierania zbioru rekordów, by pobrać nazwę tablicy.
Jak łatwo zauważyć, klasa dokumentu cusingDBDoc posiada zmienną składową m usingDBSet
typu CUsingDBSet, a klasa widoku CUsingDBView zmienną składową m_pset, która jest
wskaźnikiem do obiektu CRecordset dokumentu. Wskaźnik ten jest inicjowany w funkcji
OninitialUpdate.
Definicja klasy CUsingDBSet budowana jest w oparciu o wybory dokonane w kreatorze
AppWizard. Wybraliśmy tablicę Student, posiadającą trzy kolumny: StudentlD, Name i GradYear. Jak
widać, klasa ta ma trzy związane z nimi zmienne (linie 9-11). Typy danych i nazwy zmiennych
uzyskujemy korzystając z informacji dostarczanych przez samą bazę danych. Zmiennym tym są w
konstruktorze przypisywane domyślne wartości (linie 33-35). Konstruktor przypisuje również wartość
początkową zmiennej m_nFields (linia 36), informująca zbiór rekordów, ile jest tu kolumn.


Bazy danych i widok Record 645
Podczas tworzenia egzemplarza obiektu konstruktorowi cusingDBSet można przesłać wskaźnik do
obiektu CDatabase (linia 29). Jeśli wskaźnik ten ma wartość NULL (tak jak w tym przykładzie), bazowa
klasa CRecordset utworzy obiekt CDatabase i aby połączyć się z bazą danych, wezwie funkcję
CDatabase: :0pen. Przedtem jednak wzywana jest wirtualna funkcja GetDefaułtConnect (linia 41), która
zwraca łańcuch połączenia (linia 43). Łańcuch ten informuje obiekt CDatabase, z którym źródłem
danych ma się połączyć.
Wewnątrz funkcji CRecordset: :0pen przyzywana jest w linii 46 funkcja GetDe-faultSOL. Funkcja
CRecordset: :0pen konstruuje standardową instrukcję SQL SELECT i wykonuje zapytanie. Konstruowana
tutaj instrukcja SQL będzie mieć postać "SELECT * FROM Student". Instrukcja ta pobiera z tablicy Student
zawartość wszystkich rzędów i przechowuje je w buforze rekordu. Po otwarciu zbioru rekordów
będziemy mogli przejrzeć pobrane rekordy i sięgać do danych zapisanych w kolumnach. Klasa
CRecordset posiada również funkcję Requery, która wykonuje zapytanie ponownie, aby odświeżyć
rekordy w buforze, bez konieczności ponownego zamykania i otwierania zbioru rekordów.
Odpowiednie znaczniki sygnalizują, czy bieżący rekord (kursor) znajduje się na początku, czy na
końcu zbioru. Obecność tych znaczników możemy sprawdzić za pomocą funkcji ISBOF (początek pliku) i
ISEOF (koniec pliku). W kodzie przedstawionym na listingu 24.3 pokazana została funkcja przeszukująca
zbiór rekordów.
Listing 24.3. LST25_3.CPP - przeszukiwanie zbioru rekordów
1 void CMyView::0nlterate3et()
2 (
3 // ** Otwórz zbiór rekordów
4 CMyRecordSet rs(NULL); O
5 rs.Open(); @
6
7 // ** Sprawdź, czy nie jest pusty
8 if(rs.IsBOF())
9 return;
10
11 // ** Za pomocą funkcji Process
12 // ** przejrzyj dane rekord po rekordzie
13 while(!rs.IsEOF() ) O
14 {
15 DoSomeFunction(&rs);
16 rs.MoveNext() ;
17 }
18 }
O Tworzymy obiekt klasy wywiedzionej z klasy CRecordset.


646 Poznaj Visual C++ 6
Otwieramy połączenie ze zbiorem rekordów.
Upewniamy się, że zbiór nie jest pusty.
O Wykonujemy pętlę sięgając do każdego z rekordów.
Zmienianie danych zapisanych w bazie
Możliwość zapytywania baz danych i pobieranie zawartych w nich informacji jest bardzo przydatną
sprawą, ale większości aplikacji to nie wystarcza. Powinniśmy mieć jeszcze możliwość dodawania,
usuwania i modyfikowania rekordów zapisanych w bazie danych. Szczęśliwie klasa CRecordset
automatycznie tworzy większość kodu związanego z tymi operacjami.
Wyjątki związane z bazami danych
Należy mieć świadomość, że wiele funkcji klasy Ckecordset, takich jak open (), AddNew.o, Edit() czy
Updatet) w przypadku pojawienia się problemów uruchamia wyjątek klasy CDBException. Dlatego
odwołania do tych funkcji powinny być obramowane za pomocą instrukcji try/catch. Pomoc przy
usuwaniu błędów związanych z wyjątkami w bazach danych można uzyskać zaznaczając w menu
Tools programu narzędziowego Tracer opcję Database Tracing.
Dodawanie do bazy danych nowego rekordu odbywa się w trzech etapach. Najpierw przywoływana
jest funkcja AddNew, która ustawia zbiór rekordów w tryb dodawania (ang. add) rekordów i przypisuje
polom wartość NULL. Następnie uaktualniana jest zawartość pól, w których chcemy zapisać nowe
rekordy. Oznacza to po prostu przypisanie odpowiednich wartości zmiennym składowym klasy
CRecordset. Na koniec przyzywana jest funkcja Update, która tworzy w bazie danych nowy rekord i
wyłącza tryb dodawania rekordów. W zbiorach rekordów typu snapshot, aby sięgnąć do nowo dodanych
rekordów, należy skorzystać z funkcji Requery.
Modyfikowanie już istniejącego rekordu odbywa się z kolei w czterech fazach. Najpierw ustawiamy
bieżący rekord na rekordzie, który chcemy zmodyfikować. Następnie wzywamy funkcję Edit, która
ustawia zbiór rekordów na tryb edycji (ang. edit). Następnie zmieniamy wartości pól. Na koniec
przyzywamy funkcję Update, która zapisuje wartości w bazie danych i kończy tryb edycji.
Z kolei usuwanie danych wykonywane jest w ramach jednego posunięcia. Wzywamy po prostu
funkcję Delete, która usuwa bieżący rekord. Rekord jest usuwany zarówno ze zbioru rekordów, jak i z
bazy danych. Następnie musimy zmienić bieżący rekord, ponieważ próba sięgnięcia do usuniętego
rekordu wywoła komunikat o błędzie.


Bazy danych i widok Record 647
Wiązanie pól z tablicami bazy danych
Za każdym razem, gdy wykonywana jest operacja uaktualniania lub przewijania, dokonuje się
wymiana informacji między bazą danych a buforem. Jak można się było przekonać, zbiór rekordów ma
osobną zmienną składową dla każdej kolumny zapytania. To, która zmienna jest przypisana do której
kolumny, definiowane jest wewnątrz funkcji DoFieldExchange. Na listingu 24.4 została przedstawiona
funkcja DoFieldExchange klasy cusingDBSet pochodzącej z przykładu UsingDB.
Funkcja DoFieldExchange jest przyzywana automatycznie, gdy zachodzi potrzeba jednocześnie
pobrania i zachowania wartości pól. Dostarczane przez bibliotekę MFC makroinstrukcje zaczynające się
od liter RFX (od ang. Record Fieid Exchange, wymiana zawartości pól rekordu) służą do wymiany
danych określonego typu między zmienną składową zbioru rekordów a tablicą bazy danych. Drugi
parametr przesyłany do makroinstrukcji RFX jest nazwą kolumny w tablicy bazy danych. Trzeci
parametr jest zmienną składową, która ma przechować jego wartość. Warto zwrócić uwagę na
komentarze z linii 3 i 8. Nie należy ich usuwać ani edytować, ponieważ są potrzebne kreatorowi
CIassWizard.
Listing 24.4. LST25_4.CPP - funkcja DoFieldExchange
1 void CUsingDBSet::DoFieldExchange(CFieldExchange* pFX) O
2 {
3 //((AFX_FIELD_MAP(CUsingDBSet)
4 pFX->SetFieldType(CFieldExchange::outputColumn); @
5 RFX_Long(pFX, _T("[StudentID]"), m_StudentID);
6 RFX_Text(pFX, _T("[Name]"), m_Name);
7 RFX_Int(pFX, _T("[GradYear]"), m_GradYear);
8 //)}AFX_FIELD_MAP
9 }
O Funkcja DoFieldExchange jest przyzywana przez szkielet aplikacji do pobierania lub uaktualniania
wartości kolumn zbioru rekordów
Informujemy, że poniższe zmienne składowe są polami wyjściowymi (ang. output fields), a nie
wprowadzanymi parametrami (ang. input parameters)
Wymieniamy dane między zmiennymi składowymi zbioru rekordów a tablicą bazy danych


648 Poznaj Visual C++ 6
Widok Record
Jeśli zdecydujemy w kreatorze AppWizard, że aplikacja powinna korzystać z bazy danych, klasa
widoku aplikacji zostanie domyślnie wywiedziona z klasy CRecordview. Klasa CRecordview jest
podklasą klasy CFormView tworzącej widok przypominający formularz. Formularz reprezentowany jest
przez pozbawiony tytułu i obramowania szablon okna dialogowego zajmujący cały obszar roboczy okna
widoku. Klasa CRecordview dodaje klasie CFormView możliwości wynikające z połączenia widoku z
rekordami bazy danych za pomocą podklasy CRecordset. Kontrolki dodawane do szablonu okna dialo-
gowego mogą być łączone bezpośrednio ze zmiennymi składowymi, które są uaktualniane poprzez
pobranie wartości zapisanych w polach bazy danych. Kreator AppWizard dodaje również do widoku menu
Record i ikony paska narzędziowego umożliwiające użytkownikowi przewijanie rekordów znajdujących
się w zbiorze rekordów. Dzięki temu widok jest automatycznie uaktualniany w miarę pojawiania się
nowych rekordów.
Edytowanie szablonu widoku Record f
Szablon okna dialogowego widoku Record wygląda trochę inaczej niż inne szablony tego rodzaju,
ponieważ nie posiada tytułu ani obramowania, niemniej kontrolki dodaje się i edytuje tak'samo jak w
przypadku innych okien dialogowych. Zazwyczaj dla każdego z pól formularza, które będzie wyświetlać
dane, do formularza dodawana jest osobna kontrolka. Następnie kontrolki są przypisywane zmiennym
składowym podklasy klasy CRecordset.
Przykładowy program UsingDB korzysta z dwóch takich kontrolek. Jedna wyświetlać będzie
nazwisko studenta, a druga rok ukończenia studiów. Bazujący na widoku Record program UsingDB
tworzymy w poniższy sposób.
Projektowanie szablonu okna dialogowego widoku Record
1. W panelu ResourceView rozwiń gałąź folderu Dialog i kliknij dwukrotnie IDD_USIN-GDB_FOBM. W
edytorze zasobów pojawi się szablon okna dialogowego.
2. Kliknij komentarz TODO: Place Form Controls Herę (Tutaj umieść kontrolki formularza) i aby go
usunąć, wciśnij przycisk Delete.
3. W pasku narzędziowym Controls wybierz przycisk symbolizujący statyczny tekst (ang. static text}.
Dodaj kontrolkę Text w górnym lewym krańcu pola dialogowego, tak jak to widać na rysunku 24.8.
4. Wprowadź tytuł kontrolki Text. Tutaj Student &Name,
5. W pasku narzędziowym Controls wybierz przycisk odpowiadający kontrolce pola edycji. Dodaj ją po
prawej stronie tekstu Student Name.
6. Na liście kombinowanej ID wpisz IDC NAME.
7. W pasku narzędziowym Controls wybierz przycisk symbolizujący statyczny tekst. Dodaj kontrolkę
Text pod poprzednią kontrolka Text (Student Name).


Bazy danych i widok Record 649
8. Wpisz tytuł kontrolki. Tutaj Graduation SYear.
13 Eto idi yiert iftimi filwwt
6utó j.9^ loofe
;e) ,ia 03 . e :a- ;- :;n

^rów. ab " -li^? ^|f

^lai
^i


[s?f W'""" ^J: |


CU;tlgDBView 'ji^lc^M
m&r^,m:J

'
i

?

|l; CU..ngD8V.. ^J 1 " ::'' fS ' ! i: :


".,.-."-.,-",,.
,.,,...^.^^;",;,,,,,.^.2l



> ,1, , , l . . . . l , , . . t . , , . l . , , i l , , , i i , , , , l , , , , l
. , , , . , , , , l , , , , i , , , , i , . , ,





..,,,.,",...... ,,. --"a||iK","^ - ., BB11
: , ,E!:li6, 11 s



^




; SIl.n.B l" -* "
Qo
G.tii>i:. P f "
asa
: B3 ż ] ^ EED a li-
ca B
*t 9
@ ^
e B





l ....


icte^.|an.^*h|iB FW |





"B SlilSK^SMiWijiEB1'''';









Rysunek 24.8. Szablon widoku Record w programie UsingDB
9. Na pasku narzędziowym Controls wybierz przycisk odpowiadający kontrolce pola edycji. Dodaj ją po
prawej stronie tekstu Graduation Year.
10. Na liście kombinowanej ID wpisz IDC_YEAR. Szablon okna dialogowego powinien teraz wyglądać
tak jak na rysunku 24.8.
Wiązanie kontrolek z polami zbioru rekordów
Każda z kontrolek pól edycji szablonu dialogowego może zostać powiązana z polem bazy danych.
Powiązanie jest wykonywane poprzez przypisanie zmiennej kontrolce Edit, która będzie powiązana z
określoną zmienną składową klasy CRecordset. Klasa widoku CUsingDB przechowuje wskaźnik do
obiektu CUsingDBSet w jego zmiennej składowej m_p3et. Za pomocą kreatora CIassWizard można
powiązać zmienną składową obiektu m_pSet z kontrolką Edit.
W tym celu należy wykonać następujące czynności.
Przypisywanie kontrolek do pól bazy danych za pomocą kreatora CIassWizard
1. W panelu ResourceView rozwiń gałąź folderu Dialog i kliknij dwukrotnie IDD_USIN-GDB_FORM. W
edytorze zasobów pojawi się szablon dialogowy.
2. Zaznacz pierwsze pole edycji i wciśnij Ctri+W (lub w menu skrótów wybierz polecenie
CIassWizard), żeby uruchomić kreator CIassWizard.
3. Wybierz kartę Member Variables.


650 Poznaj Visual C++ 6
4. Z listy Control IDs wybierz identyfikator kontrolki Edit (tutaj IDC_NAME), a następnie kliknij przycisk
Add Variable. Pojawi się okno dialogowe Add Member Varia-ble. Dwukrotnie klikając
identyfikator kontrolki możesz również dodać dla niej zmienną składową.
5. Rozwiń listę kombinowaną Member Variable Name. Wyświetlona zostanie lista zmiennych zbioru
rekordów taka jak na rysunku 24.9. Wybierz zmienną składową, którą chcesz powiązać z kontrolką
Edit. Tutaj m_pSet->m_Name.

De?CT^tion:
CSIring with tength yaMation
Rysunek 24.9. Przypisywanie zmiennej zbioru rekordów kontrolce Edit
6. Z listy kombinowanej Category wybierz kategorię zmiennej. Tutaj Value.
7. Z listy kombinowanej Variable type wybierz typ zmienne. Tutaj CString.
8. Kliknij OK.
9. Z listy Control IDs wybierz identyfikator IDC_YEAR, po czym kliknij przycisk Add Variable.
10. Rozwiń listę kombinowaną Member Variable Name. Z listy wybierz m_pSet->m_GradYear.
11. Z listy kombinowanej Category wybierz kategorię zmiennej. Tutaj Value.
12. Z listy kombinowanej Variable type wybierz typ zmiennej. Tutaj int.
13. Aby zamknąć okno dialogowe Add Member Variable, kliknij OK.
14. Aby zamknąć kreator CIassWizard, kliknij przycisk OK.
Po zbudowaniu i uruchomieniu aplikacji program będzie się automatycznie łączył ze źródłem
danych Student Registration, a widok Record wyświetli w odpowiednich polach zawartość pierwszego
rekordu tablicy Student. Za pomocą strzałek u góry możemy zmieniać wyświetlane rekordy. Okno
aplikacji pokazane zostało na rysunku 24.10.


Bazy danych i widok Record 651

Rysunek 24.10. Program UsingDB w działaniu
PATRZ TAKŻE
Więcej informacji na temat projektowania okien dialogowych można znaleźć w rozdziale 3.
K/asę CFormYlew opisywaliśmy w rozdziale 18.


Wyszukiwarka

Podobne podstrony:
BAZY DANYCH Streszczenie z wykładów
Strona polecenia do bazy danych
2004 11 Porównanie serwerów relacyjnych baz danych Open Source [Bazy Danych]
MySQL Mechanizmy wewnętrzne bazy danych
Bazy danych w CAD
Postać normalna (bazy danych) – Wikipedia, wolna encyklopedia
bazy danych
01 Projektowanie relacyjnej bazy danych Czym jest relacyj
2004 05 Rozproszone fraktale [Bazy Danych]
bazy danych projekt infor w projekcie
Bazy danych(1)

więcej podobnych podstron