Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Visual Basic в примерах.docx
Скачиваний:
12
Добавлен:
18.08.2019
Размер:
1.1 Mб
Скачать

Отношения родитель/потомок между элементами управления данными

Как правило, между таблицами базы данных существуют отношения родитель/потомок (то есть связь «один-ко-многим»). Например, одно издательство публикует много книг. В таком случае родителем яв­ляется запись об издательстве, а потомками будут записи из таблицы Titles о книгах, им опубликованных.

Хорошо было бы представить эти от­ношения визуально. Построим форму, по­казывающую книги, связанные с каждым издательством. В проекте будет два элемента управления данными: первый создает набор записей обо всех издатель­ствах, второй - динамически изменяется так, чтобы показывать только книги, выпущенные издательством, которое соответствует текущей записи первого набора.

Практикум –

создание формы, иллюстрирующей отношения родитель/потомок

  1. Создайте новый проект. Поместите в форму поле ввода, две метки, элемент MS FlexGrid и два элемента управления данными. Пред­варительно необходимо добавить элемент MS FlexGrid к панели инструментов. От­кройте диалоговое окно Components и вы­берите Microsoft FlexGrid Control 6.0 (этот элемент находится в файле Msflxgrd.ocx).

  2. Присвойте свойству Caption метки Labell значение «Издательство». Для второй метки оставьте свойство Caption пустым, оно будет изменено во время выполнения программы (см. рис.):

  1. Элемент управления данными Datal должен создать набор записей обо всех издательствах. Он будет родителем. Установите для него свойство DatabaseName равным пол­ному пути к копии базы Biblio.mdb. Затем установите свойство RecordSource равным Publishers, свойству Caption также присвойте значение «Издательства». Это будет на­поминать пользователю о том, что элемент управления данными служит для навигации по одноименной таблице.

  2. Элемент управления данными Data2 должен сформировать набор записей о кни­гах, которые связаны с текущей записью набора, созданного элементом Datal. Установите свойство DatabaseName равным полному пути к копии базы Biblio.mdb. Оставьте пока свойство RecordSource для элемента Data2 пустым, а свойство Visible установите равным False. Вы будете сами управлять этим элементом, так что пользователю его видеть не следует. Свойству Caption присвойте значе­ние «Названия». Элемент во время выполнения не отображается, но при проектиро­вании обязательно появится на экране, так что неплохо бы показать, для чего он используется.

  3. Для элемента Textl задайте свойство DataSource равным Datal, а свойство DataField равным Name. Теперь в этом поле будет отображаться на­звание издательства из текущей записи набора, созданного элементом Datal.

  4. Для элемента MS FlехGrid задайте свойство DataSourse равным Data2. Не забывайте, что в этом элементе должны отображаться книги, опубликованные текущим издательством. Во время выполнения программа будет запрашивать у эле­мента управления данными соответствующий набор записей.

  5. Поскольку табличный элемент управления самостоятельно определяет размеры яче­ек, может получиться так, что часть информации будет «обрезана». Поэтому разрешим пользователю изменять параметры сетки. Задайте для свойства AllowUserResizing значение 3 - flexResize Both. В результате с по­мощью мыши можно будет менять высоту строки и ширину колонки. Позже будет показано, как уве­личивать или уменьшать шири­ну колонки из программы, что­бы. она точно соответствовала размеру отображаемого поля.

  6. Теперь придется написать немно­го кода. Дважды щелкните по эле­менту Datal и выберите событие Reposition (Изменение пози­ции). Добавьте следующий код в обработчик этого события:

Private Sub Data1_Reposition()

Dim IPubID As Long

IPubID = Data1.Recordset!PubID

Data2.RecordSource = "SELECT * FROM TITLES WHERE PubID = " & IPubID

Data2.Refresh

End Sub

Вы просите выбрать все записи из таблицы Titles, для которых поле PubID равно значению переменной IPubID, где хранится значение поля PubID из текущей записи в наборе, созданном элементом управления данными Datal.

  1. В обработчик события Text l_Change для поля ввода добавьте следующий код:

Private Sub Text1_Change()

Label2.Caption = "Название издательства: " & Text1

End Sub

10. Запустите программу.

С помощью навигационных кнопок элемента Datal пройдитесь по набору записей из таблицы Publishers. Понаблюдайте, как в таблич­ном поле отображаются книги, опубликованные издательством, которое указано в текущей записи.

Как это работает

Частью процедуры инициализации формы является вызов содержащихся в ней элементов управления данными. Первая запись таблицы Publishers ста­новится текущей. При навигации по набору записей Publishers в связанном поле ввода с помощью элемента управления данными Datal отображается назва­ние издательства из текущей записи. Заметьте, что текст метки Label2 изме­няется в соответствии с названием издательства.

Во время инициализации элемента Datal и при каждом перемещении к но­вой записи происходит событие Reposition (Изменение позиции) и вызывается его обработчик. Следовательно, это самое подходящее место для кода, с помощью которого извлекаются названия книг, опубликованных текущим издательством. Вы динамически создаете текст SQL-запроса и указываете его в качестве значе­ния свойства RecordSource элемента Data2. Затем вызываете метод Refresh эле­мента Data2 для выполнения запроса. Поскольку элемент Data2 - это значение свойства DataSource элемента MS FlexGrid, все записи из набора, созданного Data2, автоматически отображаются в табличном поле.

В результате выполнения процедуры Datal_Reposition, срабатывающей при смене текущей записи, изменяется значение в поле ввода. А это влечет за собой инициализацию события Change для поля Textl. Следовательно, запускается на выполнение и процедура Textl_Change, которая берет содержимое поля ввода, то есть название издательства, и отображает его в тексте метки Label2.

Дополнительная информация

Для некоторых издательств в базе данных не указано ни одной книги. Найдите такие, двигаясь по набору записей с помощью навигационных кнопок. К сожалению, некорректный ввод ин­формации - недостаток всех унаследованных баз данных.

Еще раз взглянем на код обработчика события Reposition для элемента Datal.

Private Sub Data1_Reposition()

Dim IPubID As Long

IPubID = Data1.Recordset!PubID

Data2.RecordSource = "SELECT * FROM TITLES WHERE PubID = " & IPubID

Data2.Refresh

End Sub

Помните, в предыдущих главах говорилось о первичных и внешних ключах? Так вот, поле PubID является первичным ключом для таблицы Publishers - в разных записях оно имеет несовпадающие значения. Следовательно, нужно взять значение этого поля для некоторого издательства и найти в таблице Titles все записи, связанные с этой организацией. В таблице Titles поле PubID является внешним ключом. В каждой записи о книге в таблице Titles хранится значе­ние идентификатора PubID издательства, опубликовавшего книгу.

Всякий раз, когда изменяется позиция указателя в элементе управления дан­ными Datal, значение поля PubID в новой текущей записи считывается в пере­менную IPubID. Восклицательный знак показывает, что вы хотите обратиться (прочитать или записать) к некоторому полю в наборе записей; он отделяет на­звание набора от названия поля - Recordset!field. Эта нотация (обозначение) используется и в DAO, и в ADO, так что в следующих уроках будет рассмотрена более подробно.

Получив значение PubID, вы создаете простое предложение на языке SQL и присваиваете его в качестве значения свойству RecordSource элемента управ­ления данными Data2. Тем самым элементу Data2 сообщается о необходимости извлечь из таблицы Titles все записи, в которых поле PubID равно значению пе­ременной IPubID - уникальному идентификатору издательства.

Затем выполняется метод Refresh, и в результате создается новый набор записей в соответствии с только что установленным значением свойства RecordSource. По сути дела, вы создали динамический SQL-запрос, то есть сформировали запрос «на лету», во время выполнения программы, подставив значение переменной IPubID, а не вставляли текст запроса в код. Таким образом, запрос изменяется в зависимости от значения поля PubID в текущей записи об издательстве.

Того же результата можно добиться и без временной переменной IPubID. До­статочно подставить значение идентификатора издательства PubID непосред­ственно в текст запроса:

Data2. RecordSource = «SELECT * FROM TITLES WHERE PubID = " & _

Datal.Recordset!PubID

Data2.Refresh

Как видите, формирование динамического SQL-запроса заняло всего одну строчку кода. Однако для отладки лучше оставить первоначальный вариант. А ког­да вы получше освоитесь с Visual Basic, второй способ, который экономит время на одном присваивании переменной, будет казаться вам проще и удобнее.

РАБОТА С ДАННЫМИ ЧЕРЕЗ ИНТЕРФЕЙС

DAO

На предыдущих занятиях мы уже работали с DAO (используя элемент управления Data). Теперь более подробно.

DAO (Data Access Object) – это набор объектов, таких как Database (база данных), TableDef (таблица базы данных), Recordset (набор полученных записей из таблицы, расположенный в оперативной памяти), QueryDef (запрос). Эти объекты позволяют обращаться и манипулировать данными программным способом.

Пользователь не обращается напрямую к базе данных. Запросы адресованы не физическому файлу, а ядру базы данных. Именно оно выполняет все операции и возвращает результаты VB – программе.

Ядро базы данных – объект DBEngine

Как уже говорилось, база данных (например, Access) состоит из таблиц, в кото­рых хранится информация. База данных может содержать прекрасно организован­ные, важные сведения. Однако на нижнем уровне база данных - это просто файл. Она не умеет манипулировать информацией. По существу, mdb-файл инертен.

И вот тут-то на сцену выходит database engine (ядро базы данных). Это программа, которая и отвечает за управление ин­формацией в базе данных. Когда мы хотим найти все книги не­которого издательства, то отправляем запрос ядру базы данных, а оно уже анализирует, какую информацию требуется извлечь и находит ее в файле базы данных. Именно ядро базы данных ма­нипулирует хранящейся в базе информацией. Поэтому при программировании Access на самом деле программируется Jet - ядро базы данных Access.

Пример ядра базы данных - Jet

На рынке представлено много различных ядер баз данных, но именно Jet являет­ся «родным» для Visual Basic и Access. Jet может управлять и другими видами дан­ных, поэтому, изучая Jet, вы приобретаете знания, которые сможете применить для работы с другими хранилищами информации. Jet - это мозг любой базы данных.

Ядро Jet «располагается» между программой на Visual Basic и файлами базы данных.

Оно может читать не только файлы базы данных, но и текстовые файлы, а также электронные таблицы.

Программист, работающий на Visual Basic, использует одни и те же приемы для работы с данными любых форматов, поддерживаемых Jet. По мере чтения книги вы увидите, что Jet выполняет за человека всю черновую работу. Поэтому вы сможете научиться создавать базы данных с помощью кода на Visual Basic даже в том случае, если на вашей машине не установлен Access.

Начинка ядра - DLL

Ядро базы данных Jet - это не отдельная программа, а группа Dynamic Link Libraries (DLL - динамически подключаемая библиотека). Что такое DLL? Это файлы, которые связываются с вашей программой динамически, то есть во время ее выполнения. Этим они отличаются от статически подключаемых библиотек, которые являются частью любой связанной с ними программы. Представьте себе, что на вашем ПК есть четыре программы, работающие с базой данных Access.

Если бы они были связаны статически, то весь код, составляющий ядро Jet, был бы включен в каждую из четырех программ. До появления Windows так оно и было. Теперь, однако, DLL-библиотеки лежат отдельно на диске и вызываются в процессе работы любой программой, которой они требуются. Все изменения в ядре Jet распространяются в виде обновленных DLL, так что любая программа, динамически связанная с ними, использует новшества без изменения собственно­го кода и перекомпиляции (см. рис. 1.15).

DLL, являющиеся «начинкой» Jet, автоматически связываются с программой на Visual Basic во время выполнения. Jet преобразует запросы от программы в фи­зические операции над mdb-файлом или другим источником данных.

Основное достоинство Jet состоит в том, что, работая с ним, можно использовать один и тот же код и приемы программирова­ния вне зависимости от источника, к которому обращен запрос: к базе данных, текстовому файлу или электронной таблице. За все отвечает Jet - оно считывает и записывает данные в хранилище. Оставаясь «за сценой», Jet выполняет вес служебные операции: индексирование таблиц, обеспечение безопасности, блокировку и многое другое. Кроме того, постоянно используется процессор запросов Jet, который обрабатывает запросы на извлечение данных. Эти запросы обычно формулируются с помощью языка SQL (Structured Query Language – структурированный язык запросов). Проанализировав запрос, Jet затем применяет процессор результатов для того, чтобы вернуть результаты в программу на Visual Basic.

Самодостаточность Jet

Ядро Jet выполняет роль интерфейса между хранящимися в таблице данны­ми и VB-приложениями. Для разработчиков это означает, что конечному пользо­вателю вовсе не обязательно устанавливать на свой ПК программу Access. Ваши программы самодостаточны. Иными словами, кроме файлов, включенных в дист­рибутив (а это Jet и файлы на Visual Basic), не потребуются никакие другие про­граммы. Что может быть проще? Получается, что пользователям даже знать не надо о том, какую базу данных вы используете. Для них это безразлично.

Чтобы с помощью DAO можно было обратиться к данным программным способом, сначала нужно с помощью объекта DBEngine открыть рабочую область (Workspace).

Объект DBEngine – объект высшего уровня в объектной модели DAO. Он содержит и управляет всеми остальными объектами DAO.

Объект Workspace определяет сеанс пользователя (рабочую область) и устанавливает, какое приложение будет взаимодействовать с данными. Если база данных открывается без специфицирования объекта Workspace, по умолчанию используется DBEngine.Workspace(0)

Сеанс пользователя начинается, когда пользователь регистрируется (открывает базу) и заканчивается, когда пользователь выходит из приложения. Все операции, выполняемые во время сеанса, формируют одну рабочую область. В DAO сеансы реализованы как объекты Workspace.

Пример создания БД:

Dim db as Database

Set db = DBEngine.Workspaces(0).CreateDatabase ("С:\ПробнаяБД.mdb", dbLangGeneral)

Пример создания рабочей области:

Dim NewWS Workspace

Set NewWS = DBEngine.CreateWorkspace ("НоваяWS”, “Администратор”, “Пароль“, dbUseJet)

Каждая рабочая область имеет ассоциированные с ней идентификатор пользователя и пароль.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]