Документ взят из кэша поисковой машины. Адрес оригинального документа : http://www.abitu.ru/en2002/closed/viewwork.html?work=49
Дата изменения: Fri May 5 15:25:53 2006
Дата индексирования: Tue Oct 2 02:22:21 2012
Кодировка: koi8-r

Поисковые слова: п п р п р п р п р п р п р п р п р п р п

Использование классов при программировании

приложений баз данных.

Автор: Грегер Ольга Сергеевна, 9-А класс гимназии ?86, г. Нижний
Тагил, Свердловская обл. greger@uraltelecom.ru


Научный руководитель: Грегер Сергей Эдуардович


Введение.

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

В прошлом году я создала программу для психологов. Основной ее задачей
было:
1. Удобное хранение информации (результаты тестов).

2. Выполнение тестов на компьютере и их последующая обработка.
3. Возможность удобного просмотра результатов тестов, сравнение с
предыдущими результатами.
4. Просмотр психологической атмосферы класса с помощью наглядных средств
(графики, таблицы).
5. Автоматическая обработка информации и создание графа определяющего
микро-группы внутри класса и их лидеров

Моя программа была рекомендована для распространения в школах Нижнего
Тагила. На данный момент она уже работает в некоторых из них.

В процессе работы над этой программой выявилось несколько вариантов
ее усовершенствования. Например, формы заполнения тестов по некоторым
сферам, в общей сложности их 4 (Мотивационная, Интеллектуальная,
Мыслительная и Познавательная), построены по однотипной модели. А именно:
форма, несколько текстовых блоков, график и кнопки управления. Конечно же,
здесь используются и метки, но образованы они по типу текстовых блоков.
Поскольку в моем случае (хотя такое происходит довольно часто) интерфейс
однотипен, и изменяется только количество текстовых блоков и меток, то
можно создать одну форму.
Такая форма будет являться неким шаблоном, с помощью которого можно
будет создавать другие формы с определенным количеством объектов. Очень
важно отметить то, что количество форм созданных по данному шаблону
неограниченно.

Основным достоинством такого принципа построения программы является то,
что в памяти компьютера будет храниться только одна форма, заменяющая
множество однотипных.


Создание собственного источника данных.

Создадим класс для установления соединения с базой данных. В этом
классе должно быть два свойства: строка соединения и строка запроса. В
строке соединения я должна описать, какой провайдер используется для
соединения, какой путь к моей базе данных и соответственно ее имя. В строке
запроса содержится выражение на языке SQL, необходимое для доступа к
данным.
Во всех примерах я буду использовать базу данных db2.mdb. Ниже
приводится код данного класса:

DBClass.cls

Option Explicit
Private WithEvents ConRs As ADODB.Recordset
Private dbConn As ADODB.Connection
Private mvarConStr As String
Private mvarSQLStr As String


Private Sub Class_Initialize()
Set dbConn = New ADODB.Connection
End Sub

Private Sub Class_GetDataMember(DataMember _
As String, Data As Object)
Set Data = ConRs
End Sub


Public Property Let ConStr (ByVal vData As String)
mvarConStr = vData
dbConn.Mode = adModeShareDenyNone
dbConn.CursorLocation = adUseClient
dbConn.Open mvarConStr
End Property


Public Property Get ConStr () As String
ConStr = mvarConStr
End Property



Public Property Let SQLStr (ByVal vData As String)
mvarSQLStr = vData
Set ConRs = New ADODB.Recordset
ConRs.Open mvarSQLStr, dbConn, adOpenStatic, adLockOptimistic

End Property




Public Property Get SQLStr () As String
SQLStr = mvarSQLStr
End Property



Использовать данный класс в приложении можно таким образом:

Dim myRS As DBClass
Dim myRS1 As DBClass

Private Sub Form_Load()

Set myRS = New DBClass
myRS.ConStr = "PROVIDER=Microsoft.Jet.OLEDB.4.0;"
myRS.ConStr = myRS.ConStr & "Data Source=" & App.Path & "\db2.mdb;"
myRS.SQLStr = "select * from tbldeti"
Set DG.DataSource = myRS

Set myRS1 = New DBClass
myRS1.ConStr = "PROVIDER=Microsoft.Jet.OLEDB.4.0;"
myRS1.ConStr = myRS1.ConStr & "Data Source=" & App.Path &
"\db2.mdb;"
myRS1.SQLStr = "select * from tbltich"
Set DG1.DataSource = myRS1
End Sub

В моей форме использованы два объекта типа DataGrid с именами DG и
DG1. Они служат для отображения содержимого выбранных таблиц. Выбор нужных
таблиц осуществляется установкой свойства SQLStr у переменных myRS и
myRS1, объявленные как DBClass. Наш класс вывел из форм описание соединения
и создания источника данных. Но из приведенного кода видно, что значение
ConStr одинаково. Это означает, что созданы два одинаковых объекта типа
ADODB.Connection. Это приводит к нерациональному использованию памяти в
случае соединения с таблицами из одной базы данных. Для решения этой
проблемы создадим класс DBConn.







Private mvardbConn As adodb.connection
Private mvarConStr As String


Private Sub Class_Initialize()
Set mvardbConn = New ADODB.Сonnection
End Sub

Public Property Let ConStr(ByVal a As String)
mvarConStr = a
mvardbConn.Mode = adModeShareDenyNone
mvardbConn.CursorLocation = adUseClient
mvardbConn.Open mvarConStr

End Property
Public Property Get ConStr() As String
ConStr = mvarConStr
End Property
Public Property Get dbConn() As adodb.connection
Set dbConn = mvardbConn
End Property



Теперь я приведу код видоизмененного класса DBClass. Из за того, что я
вывела Connection из его кода, класс приобрел такой вид:


DBClass.cls

Option Explicit
Private WithEvents ConRs As ADODB.Recordset
Private mvardbConn As ADODB.Connection
Private mvarSQLStr As String


Private Sub Class_Initialize()
Set mvardbConn = new ADODB.Connection
End Sub

Private Sub Class_GetDataMember(DataMember _
As String, Data As Object)
Set Data = ConRs
End Sub


Public Property Let SQLStr (ByVal vData As String)
mvarSQLStr = vData
Set ConRs = New ADODB.Recordset
ConRs.Open mvarSQLStr, mvardbConn, adOpenStatic, adLockOptimistic

End Property


Public Property Get SQLStr () As String
SQLStr = mvarSQLStr
End Property

Public Property Let dbconn (ByVal vData As adodb.connection)
Set mvardbconn = vData
End Property

Созданный мной класс уже может существовать самостоятельно, но для я
приведу код формы, в которой будет отображаться выбранная таблица. Выше я
уже приводила такой код, но из за изменений в классах он изменился:


Dim mycon As dbConn1
Dim myrs As dbCllass1
Dim myrs1 As dbCllass1

Private Sub Form_Load()
Set mycon = New dbConn1
mycon.ConStr = "PROVIDER=Microsoft.Jet.OLEDB.4.0; Data Source=" &
App.Path & "\db2.mdb;"



Set myrs = New dbCllass1
Set myrs1 = New dbCllass1
myrs.dbconn = mycon.dbconn
myrs.SQLStr = "select * from tbldeti"
Set DG1.DataSource = myrs

myrs1.dbconn = mycon.dbconn
myrs1.SQLStr = "select * from tblClass"
Set DG2.DataSource = myrs1
End Sub

Из приведенного примера видно, что код стало намного проще, нежели
было в предыдущем варианте. Это происходит из - за того, что соединение
вызывается один раз.


Создание формы как класса и работа с ним.

Теперь моя задача немного усложняется, ведь если в предыдущей главе я
создавала классы, работающие с формой, то теперь я должна создать форму
как класс, и самое главное связать ее с базой данных.
Как же сделать это? Очень просто. Начнем с самого элементарного: формы
представляют собой классы, и объединить все однотипные
формы в объектную переменную можно командой Dim. Так же возможно управлять
их работой из программы. В Visual Basic существует четыре метода для
операций с формами:

1. Load - загрузка формы в память без отображения.
2. Show - отображение ранее загруженной формы или загрузка формы с
последующим отображением.
3. Unload - скрытие формы и ее выгрузка из памяти компьютера.
4. Hide - скрытие формы без выгрузки из памяти компьютера.

Перечисленные методы предназначены для ранее сконструированных форм,
существующих в текущем проекте. Формы так же можно создавать во время
выполнения программы:

Dim myForm as Form1

Эта команда создает объектную переменную типа Form, которая может
использоваться для ссылок на уже существующие формы:

Set myForm = Form1

Так же возможно создание новых форм, для этого используется
специальное свойство New:

Set myForm = New Form1
Самое интересное, что сконструированный прототип формы может обладать
собственными свойствами и методами и даже инициировать различные события.

Создадим на форме один текстовый блок Text1 и присвоим его
свойству Index значение 0.

Для работы с текстовыми блоками, а в каждой форме их должно быть разное
количество, создадим переменную mucol, объявив ее как Public. Эта
переменная будет являться свойством для нашей формы и будет определять
количество текстовых блоков. В приведенном ниже коде создается массив
текстовых блоков, число которых определяется значением этой переменной:

Public mucol As Integer
Dim i As Integer

Private Sub Form_Load()
For i = 1 To mucol
Load Text1(i)
Text1(i).Left = Text1(i - 1).Left
Text1(i).Top = Text1(i - 1).Top + Text1(i - 1).Height
Text1(i).Visible = True
Next

End Sub
Данный код обеспечивает расположение текстовых блоков друг под другом.
Создание формы и установление ее свойств производится в
запускающей процедуре Main() из модуля Module1.bas:

Sub Main()
Dim f1 As Form1
Set f1 = New Form1
With f1
.mucol = 5
.Show
End With

End Sub

Связь формы с базой данных.

Прототип формы уже создан. Но он не удовлетворяет моим требованиям,
так как у данной формы нет связи с базой данных. Для установления такой
связи объявим в форме свойство mucol типа dbCllass1 и создадим
запускающую процедуру Main() в Module1:

Public mycon As dbConn1
Public myrs As dbCllass1
Dim f1 As Form1
Sub Main()
Set mycon = New dbConn1
mycon.ConStr = "PROVIDER=Microsoft.Jet.OLEDB.4.0; Data Source=" &
App.Path & "\db2.mdb;"

Set myrs = New dbCllass1
myrs.dbconn = mycon.dbconn
myrs.SQLStr = "select * from tbldeti"

Set f1 = New Form1
Set f1.mcol = myrs
f1.Show

Наше свойство mucol передает в форму значения из базы данных, но
не передает информацию о необходимом количестве текстовых блоков.
Для решения этой проблемы введем в класс dbCllass1 свойство
ColText, хранящее количество полей используемой таблицы.

Public Property Get colText() As Integer
mvarcolText = ConRs.Fields.Count
Set colText= mvarcolText
End Property

Используя свойство colText, изменим код формы:

Public mucol As New dbCllass1
Dim i As Integer

Private Sub Form_Load()
showform
End Sub

Public Sub showform()
Dim count As Integer
count = mucol.colText
For i = 1 To Int(count / 2)

Load Text1(i)
Set Text1(i).DataSource = mucol
Text1(i).Left = Text1(0).Left
Text1(i).Top = Text1(i - 1).Top + Text1(i - 1).Height + 50
Text1(i).Visible = True
Next
For i = 1 + Int(count / 2) To count

Load Text1(i)
If i = 1 + Int(count / 2) Then
Text1(1 + Int(count / 2)).Top = Text1(0).Top
Else
Text1(i).Top = Text1(i - 1).Top + Text1(i - 1).Height + 50

End If

Text1(i).Left = Me.Width / 2

Set Text1(i).DataSource = mucol
Text1(i).Visible = True
Next
Me.Height = Text1(Int(count / 2)).Top + Text1(Int(count / 2)).Height
+ 1000
End Sub

В данном коде описано создание и расстановка текстовых блоков. Размеры
формы изменяются в зависимости от количества текстовых блоков. Теперь
осталось заполнить их. Для этого нужно сообщить особое свойство DataField
каждому текстовому полю. Введем в класс dbCllass1 свойство ListFields и
объявим ее как коллекцию.

Private Sub Class_Initialize()
Set mvardbConn = New ADODB.Connection
Set mvarListFields = New Collection
End Sub

Ниже приведен код данного свойства:


Public Property Get ListFields() As Collection
For i = 0 To ConRs.Fields.count - 1
mvarListFields.Add ConRs.Fields(i).Name
Next
Set ListFields = mvarListFields
End Property

Из-за изменений в классе и объявления новых свойств, код формы будет
выглядеть так:

Private Sub Form_Load()
Dim count As Integer
count = mucol.colText
showform
For i = 0 To count - 1
Set Text1(i).DataSource = mucol
Text1(i).DataField = mucol.ListFields.Item(i + 1)

Next
End Sub

На данном этапе созданные классы и прототип формы позволяют
работать только с одной, предварительно указанной таблицей. Опишем
способ доступа к списку таблиц базы данных и автоматического
создания интерфейса для работы с ним. Прежде всего, необходим способ
создания списка имеющихся таблиц. Для этого используем метод
OpenSchema объекта ADODB.Connection. Этот метод возвращает объект типа
ADODB.Recordset, содержащий список всех таблиц данного соединения. Для
работы с данным методом добавим в наш класс dbConn новое свойство
Struct() типа Collection.

Private Sub Class_Initialize()
Set mvardbconn = New ADODB.Connection
Set mStruct = New Collection
End Sub

Public Property Get Struct() As Collection
Dim myrs As ADODB.Recordset
Dim constr As String
Dim mystr As String
Dim i As Integer
Set myrs = New ADODB.Recordset
Set myrs = mvardbconn.OpenSchema(adSchemaTables, TABLE_TYPE)
'constr = "select *from " & tblname
'myrs.Open constr, db, adOpenStatic, adLockOptimistic
Do Until myrs.EOF
If myrs!TABLE_TYPE = "TABLE" Then
mStruct.Add (myrs!TABLE_NAME)
End If
myrs.MoveNext
Loop
myrs.Close

Set Struct = mStruct

End Property

Для использования данного свойства добавим в наш проект форму
frmMain и вставим в неё элемент управления ComboBox с именем Combo1.
Изменим процедуру Main() следующим образом:

Public mycon As dbConn1
Public myrs As dbCllass1
Public f1 As Form1
Sub Main()
Set mycon = New dbConn1
mycon.constr = "PROVIDER=Microsoft.Jet.OLEDB.4.0; Data Source=" &
App.Path & "\db2.mdb;"

Set myrs = New dbCllass1
myrs.dbconn = mycon.dbconn
frmMain.Show

End Sub.

Добавим в форму frmMain следующий код:

Private Sub Form_Load()
For i = 1 To mycon.Struct.Count
Combo1.AddItem (mycon.Struct.Item(i))
Next
End Sub

Private Sub Combo1_Click()
Set myrs = New dbCllass1
myrs.dbconn = mycon.dbconn
myrs.SQLStr = "select * from " & Combo1.List(Combo1.ListIndex)
Set f1 = New Form1
Set f1.mucol = myrs
f1.Show

End Sub

В обработчике событий Form_Load() происходит заполнение элемента
Combo1 из свойства Struct объекта mycon. После выбора нужной таблицы из
списка мы очищаем объект myrs и устанавливаем его свойства для связи с
выбранной таблицей. Далее мы создаем новый экземпляр формы f1, и в
оперативной памяти создается массив из форм f1, которые различаются по
значению индекса. В результате этого на экране монитора возникает набор
форм, каждая из которых соответствует определенной таблице. Можно
считать, что создание интерфейсной части программы завершено. Но наш
интерфейс не содержит элементов навигации по каждой из выбранной
таблице. Поэтому следующим шагом будет разработка навигации.

Создадим форму и поместим на нее объекты для управления перемещением
по базе и кнопки для редактирования записей. Объявим в Module1 переменную
NavRS как Public, и установим в кнопках перемещения методы данной
переменной. Если теперь передать этой переменной ссылку на набор данных
какой-либо формы, то навигационная форма сможет менять положение в данном
наборе. Эта ссылка обеспечивается с помощью свойства Nav, объявленного в
классе dbCllass1. В этом свойстве хранится значение набора записи,
передаваемое форме. Передача ссылки производится в обработчике
Form_Deactivate формы Form1. Ниже приведен дополнительный код класса и
формы frmNav.

dbCllass1. cls
Public Property Get Nav() As ADODB.Recordset
Set Nav = ConRs
End Property


frmNav:
Private Sub cmdAdd_Click()
On Error GoTo AddErr
With NavRS
.AddNew
SetButtons False
End With

Exit Sub
AddErr:
MsgBox Err.Description

End Sub


Private Sub cmdDelete_Click()
On Error GoTo DeleteErr
With NavRS
.Delete
.MoveNext
If .EOF Then .MoveLast
End With
Exit Sub
DeleteErr:
MsgBox Err.Description
End Sub


Private Sub cmdEdit_Click()
On Error GoTo EditErr

SetButtons False
Exit Sub

EditErr:
MsgBox Err.Description
End Sub

Private Sub cmdCancel_Click()
On Error Resume Next

SetButtons True
NavRS.CancelUpdate

End Sub

Private Sub cmdUpdate_Click()
On Error GoTo UpdateErr

NavRS.UpdateBatch adAffectAll

SetButtons True
Exit Sub
UpdateErr:
MsgBox Err.Description
End Sub


Private Sub cmdFirst_Click()
On Error GoTo GoFirstError

NavRS.MoveFirst
Exit Sub

GoFirstError:
MsgBox Err.Description
End Sub

Private Sub cmdLast_Click()
On Error GoTo GoLastError

NavRS.MoveLast

Exit Sub

GoLastError:
MsgBox Err.Description
End Sub

Private Sub cmdNext_Click()
On Error GoTo GoNextError

If Not NavRS.EOF Then NavRS.MoveNext
If NavRS.EOF And NavRS.RecordCount > 0 Then
Beep
NavRS.MoveLast
End If
Exit Sub
GoNextError:
MsgBox Err.Description
End Sub

Private Sub cmdPrevious_Click()
On Error GoTo GoPrevError

If Not NavRS.BOF Then NavRS.MovePrevious
If NavRS.BOF And NavRS.RecordCount > 0 Then
Beep
NavRS.MoveFirst
End If

Exit Sub

GoPrevError:
MsgBox Err.Description
End Sub

Private Sub SetButtons(bVal As Boolean)
cmdAdd.Visible = bVal
cmdEdit.Visible = bVal
cmdUpdate.Visible = Not bVal
cmdCancel.Visible = Not bVal
cmdDelete.Visible = bVal
cmdClose.Visible = bVal
cmdRefresh.Visible = bVal
cmdNext.Enabled = bVal
cmdFirst.Enabled = bVal
cmdLast.Enabled = bVal
cmdPrevious.Enabled = bVal
End Sub


Form1:
Private Sub Form_Deactivate()
Set NavRS = Me.mucol.Nav
End Sub

После этих видоизменений мы получаем программу автоматического создания
форм для всех таблиц в базе данных.













На данный момент я работаю над программой ведения журналов успеваемости
по всем классам гимназии. Рассмотренные выше приемы программирования я
планирую применить в этой программе. Также в моих планах стоит разработка
серверной программы, точнее, новая версия «Психологической карты»,
описанной в данном реферате. Конечно, я буду использовать классы.










































Литература.

1. Петруцос Э. Visual Basic и VBA для профессионалов. - Санкт-Петербург:
Питер, 2000г.
2. Ресельман Б. Использование Visual Basic 6. -М: Издательский дом
«Вильямс», 1999г.
3. Дженнигс Р. Руководство разработчика баз данных на Visual Basic 6.
-М: Издательский дом «Вильямс», 2001г