1 Katedra Optoelektroniki i Systemów Elektronicznych 2 Oprogramowanie Systemów Elektronicznych Zagadnienia: Temat wykładu 1. Interfejs ODBC 2. 3. 3 Interfejs ODBC 4 Interfejs ODBC ODBC (Open DataBase Connectivity) uniwersalny interfejs programowania pozwalający aplikacjom uzyskać dostęp do dowolnej bazy danych, w której jako standard dostępu do danych jest używany język SQL. SQL (Structured Query Language) język zarządzania bazami danych takimi jak: Oracle, Informix, Sybase, Microsoft SQL Server, Paradox, Access, dbase i innych - w sumie 140 produktach. Sterownik ODBC (ODBC Driver) interpretuje zapytania SQL-a na format zrozumiały dla określonej bazy danych. Sterownik ODBC jest zwykle dostarczany przez firmę produkującą daną bazę lub przez dostawców niezależnych. Administrator źródła danych ODBC (ODBC Driver Manager) - menedżer ODBC pozwalający na konfigurowanie źródeł baz danych dostępnych na poziomie systemu operacyjnego. CRecordset klasa w MFC zawierająca zbiór rekordów bazy danych APPLICATION CRecordset SQL ODBC Driver Manager ODBC Driver DATA SOURCE APPLICATION CRecordset SQL ODBC Driver Manager ODBC Driver DATA SOURCE 5 6 Zagadnienia: 1. Interfejs ODBC 2. 3. Metoda Open otwiera zbiór rekordów. virtual BOOL Open( UINT nopentype = AFX_DB_USE_DEFAULT_TYPE, LPCTSTR lpszsql = NULL, DWORD dwoptions = none ); Parametry: nopentype typ zbioru rekordów CRecordset::dynaset Zbiór rekordów, który może być odświeżany przez wywołanie funkcji Fetch, dzięki czemu widoczne są zmiany wprowadzone do zbioru rekordów przez innych użytkowników CRecordset::snapshot Zbiór rekordów, który nie może być odświeżany bez zamykania i ponownego otwierania zbioru rekordów. CRecordset::dynamic Podobny do dynaset, ale nie dostępny w wielu sterownikach Recordset::forwardOnly Zbiór rekordów tylko do odczytu, który może być jedynie przeglądany od pierwszego do ostatniego elementu 1.1
7 8 Parametry metody Open cd. lpszsql wyrażenie SQL, które ma zostać wykonane w celu wygenerowania zbioru rekordów dwoptions znaczniki otwarcia zbioru rekordów: CRecordset::none brak opcji (wartość domyślna) CRecordset::appendOnly tylko dodawanie rekordów CRecordset::readOnly tylko odczytywanie rekordów Metoda Close zamyka zbiór rekordów. Poruszanie się po zbiorze rekordów Funkcja Opis MoveFirst Przejście do pierwszego rekordu MoveLast Przejście do ostatniego rekordu MoveNext Przejście do następnego rekordu MovePrev Przejście do poprzedniego rekordu Przejście o określoną liczbę rekordów względem aktualnej Move pozycji lub względem pierwszego rekordu SetAbsolutePosition Przejście do określonego rekordu IsBOF Czy wskaźnik znajduje się przed pierwszym rekordem? IsEOF Czy wskaźnik znajduje się poza ostatnim rekordem? GetRecordCount Zwraca liczbę rekordów CanScroll Czy można przechodzić między rekordami? Numeracja rekordów: 0 1... N N+1 BOF rekord 1 rekord N EOF 9 10 Poruszanie się po zbiorze rekordów // Open a recordset; first record is current CRecordset *m_pset; m_pset->open( ); if( m_pset->isbof( ) ) return; // The recordset is empty // Scroll to the end of the recordset, past // the last record, so no record is current while (!m_pset->iseof( ) ) m_pset->movenext( ); // Move to the last record m_pset->movelast( ); Poruszanie się po zbiorze rekordów // Scroll to beginning of the recordset, before // the first record, so no record is current while(!m_pset->isbof( ) ) m_pset->moveprev( ); // First record is current again m_pset->movefirst( ); Zliczanie liczby rekordów if (m_pset->isbof( ) && m_pset->iseof( )) m_count = 0; else { while (!m_pset->iseof( ) ) m_pset->movenext( ); m_count = m_pset->getrecordcount( ); 11 12 Dodawanie, usuwanie i modyfikowanie rekordów Funkcja Opis AddNew Dodaje nowy rekord do zbioru Delete Usuwa bieżący rekord ze zbioru Edit Umożliwia edycję bieżącego rekordu Update Zapisuje bieżące zmiany w bazie danych Requery Pozwala na odświeżenie zbioru rekordów CancelUpadate Anuluje wszystkie zalegające aktualizacje (pochodzące z AddNew lub Update) CanAppend Czy można dodawać nowe rekordy? CanUpdate CanRestart CanScroll Czy można zapisać zmiany? Czy można odświeżyć zbiór rekordów? Czy można przechodzić między rekordami? Sekwencja funkcji dodających nowy rekord // Dodanie nowego rekordu m_pset->addnew(); // Ustawienie identyfikatora w nowym rekordzie m_pset->m_id = m_count + 1; // Zapisanie nowego rekordu m_pset->update(); // Odświeżenie zbioru rekordów m_pset->requery(); // Przejście do nowego rekordu m_pset->movelast(); 1.2
13 14 Sekwencja funkcji usuwających rekord m_pset->delete(); m_pset->requery(); // aktualny rekord numer 1 --m_count; if (m_count == 0) m_currrecord = 0; --m_currrecord; m_pset->setabsoluteposition(m_currrecord); Sekwencja funkcji umożliwiających edycję bieżącego rekordu pset->edit(); // Zezwolenie na edycję bieżącego rekordu // Aktualizacja pól rekordu //... pset->update(); // Zapisanie zmian Zagadnienia: 1. Interfejs ODBC 2. 3. 15 16 Konfigurowanie źródła danych Konfigurowanie źródła danych 17 18 Konfigurowanie źródła danych Tworzenie programu przy pomocy kreatora 1.3
19 20 Tworzenie programu przy pomocy kreatora Projekt panelu czołowego Dynaset umożliwia dynamiczną pracę z rekordami, wspólnie z innymi użytkownikami. Snapshot umożliwia pracę z rekordami zawierającymi dane z chwili ich pobrania. OnFirst OnPrev OnNext OnLast OnEdit OnRemove OnUpdate OnCancelUpdate OnAdd OnRemoveAll 21 22 Łączenie obiektów z polami bazy danych Klasa widoku class CElementyView : public CRecordView { public : CElementyView(); ~CElementyView(); public: CElementySet* m_pset; long m_currrecord, m_count; // called first time after construct virtual void OnInitialUpdate(); private: void GetCount(); // ustalenie liczby rekordów // funkcje kontrolujące dostępność przycisków na panelu void EnableEdit(BOOL); void EnableNaviButtons(BOOL); 23 24 Inicjalizacja klasy widoku void CElementyView::OnInitialUpdate() { // Kod utworzony przez kreatora aplikacji m_pset = &GetDocument()->m_elementySet; CRecordView::OnInitialUpdate(); GetParentFrame()->RecalcLayout(); ResizeParentToFit(); // Kod dodany GetCount(); Liczba rekordów void CElementyView::GetCount() { if (m_pset->isbof( ) && m_pset->iseof( )) { m_count = 0; m_currrecord = 0; else { while (!m_pset->iseof( ) ) m_pset->movenext( ); m_count = m_pset->getrecordcount( ); m_currrecord = 1; 1.4
25 26 Nawigacja 1/2 void CElementyView::OnFirst() { m_currrecord = 1; void CElementyView::OnLast() { if (m_currrecord < m_count) { m_pset->movelast(); m_currrecord = m_count; Nawigacja 2/2 void CElementyView::OnPrev() { m_pset->moveprev(); --m_currrecord; void CElementyView::OnNext() { if (m_currrecord < m_count) { m_pset->movenext(); ++m_currrecord; 27 28 Edycja rekordu void CElementyView::OnEdit() { m_pset->edit(); EnableEdit(TRUE); EnableNaviButtons(FALSE); void CElementyView::OnUpdate() { UpdateData(TRUE); m_pset->update(); void CElementyView::OnCancelUpdate() { m_pset->cancelupdate(); Dodawanie rekordu void CElementyView::OnAdd() { m_pset->addnew(); // Dodanie nowego rekordu // Ustawienie identyfikatora w nowym rekordzie m_pset->m_id = m_count + 1; m_pset->update(); // Zapisanie nowego rekordu m_pset->requery(); // Odświeżenie zbioru rekordów m_pset->movelast(); // Przejście do nowego rekordu ++m_count; m_currrecord = m_count; // Uaktualnienie formularza 29 30 Usuwanie rekordu void CElementyView::OnRemove() { if ((m_count > 0) && (MessageBox("Are you sure?", "Deleting record", MB_YESNO MB_ICONQUESTION) == IDYES)){ // Usunięcie rekordu m_pset->delete(); m_pset->requery(); --m_count; if (m_count == 0) { m_currrecord = 0; m_pset->m_id = 0; m_pset->m_value = 0; --m_currrecord; m_pset->setabsoluteposition(m_currrecord); Usuwanie wszystkich rekordów void CElementyView::OnRemoveAll() { if ((m_count > 0) && (MessageBox("Are you sure?", "Deleting all records,mb_yesno MB_ICONQUESTION)==IDYES)){ // Usunięcie wszystkich rekordów while (!m_pset->iseof( ) ) { m_pset->delete( ); m_pset->movenext(); m_pset->requery(); m_count = 0; m_currrecord = 0; m_pset->m_id = 0; m_pset->m_value = 0; 1.5
31 Wygląd gotowej aplikacji 1.6