    68 Поддержание целостности дан, 

    Глава 4. Расширенные возможности программирования доступа к данным 

    Элемент управления Data или Объекты доступа к данным можно использовать 
для быс го создания приложений базы данных с минимальным объемом программирования. 
    Однако, если в приложении требуется управлять ошибками, управлять 
многопользоват ским доступом к данным и контролировать ошибки целостности 
данных, без напиа дополнительного программного кода не обойтись. 
    В этой главе освещаются расширенные возможности построения приложений базы дан 

    4.1. Поддержание целостности данных 

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

    4.1.1. Определение правил для обрабатываемой информации 

    Используя базу данных Microsoft Jet, можно определять правила, в которых 
специфиц ется, какие данные для поля или таблицы допустимы. Эти правила 
хранятся в базе дан и поддерживаются независимо от способа изменения данных.	~ 
    В базе данных Nwind имеется несколько определенных правил. Например, 
правило поля Quantity (количество заказанного товара) в таблице Order Details 
(данные nosi/ заказа) определяет, что количество должно быть больше 0. 

    Свойства, связанные с правилами 

    Средствами Visual Basic можно создавать или просматривать правила базы 
данных. С екты Field и Recordset имеют два свойства, которые связаны с правилами. 
    Следующие свойства поддерживаются только в базах данных Microsoft Jet: 
ValidationRule   Определяет критерии для правила. 
ValidationText    Текст сообщения об ошибке, которое может быть выведено в 
случае HI шения правила. 

    В следующем примере кода в окне Immediate выводятся значения свойств 
ValidationRi ValidationText для поля Quantity: 

    Sub   DisplayRule() 
    Set   rstOrders   =  dbDbl.OpenRecordset("Order   Details") '   Печатается 
  ">0" Debug.Print   rstOrders("Quantity").ValidationRule 


    Глава 4. Расширенные возможности программирования доступа	69 

    '   Печатается   "Quantity must  be   greater   than   0" Debug.Print  
rstOrders("Quantity").ValidationText End  Sub 

    Примечание: Чтобы определить правило программным способом, можно 
установить свойство Validat/onRule объекта Field. 


    Ошибки, связанные с нарушениями правил 

    Если при обновлении записи нарушается правило, возвращается ошибка 
выполнения. Свойство ValidateOnSet определяет момент, когда.йащшение правила 
вызывает ошибку. 
    Если ValidateOnSet — True, ошибка выполнения произойдет при установке 
значения поля, как показано в следующем примере: 

    recorders("Quantity").ValidateOnSet   =  True 
    recorders("Quantity").Value   =   0   '   Здесь   будет   сгенерирована   ошибка 
    recorders.Update 
    Если ValidateOnSet — False, ошибка выполнения произойдет при вызове метода 
Update, как в следующем примере:	•——
    recorders("Quantity").ValidateOnSet   =   False 
    recorders("Quantity").Value  =   0 
    recorders.Update   '   Здесь   будет   сгенерирована   ошибка 

    Обработка нарушений правил 

    Обычно, если происходит нарушение правила, следует предоставить 
пользователю возможность исправить данные и повторить попытку модификации. 
Если используется элемент ynj3aBiiejHtig__Data и имеет место нарушение 
правила, происходит событие jlrror^ Элемент управления Data выводит на экран 
значение свойства ValidationText и отменяет модификацию. Пользователь может 
изменить данные и щелкнуть элемент управления Data снова, чтобы попытаться 
повторить модификацию. 
    Чтобы предпринять различные действия в случае возвращения ошибки, можно 
добавить код к процедуре события Error. Например, можно вывести текст в 
заголовке формы, а не в окне сообщения, или подать звуковой сигнал и изменить 
свойстрд JoreColor полей (цвет литер), чтобы показать, что произошла ошибка.	"~* 
    Если в момент нарушения правила используются объекты доступа к данным, 
возвращается ошибка выполнения. Эту ошибку необходимо предусмотреть^ 
перехватить и сообщать о ней поНьзователю. 
    В следующем примере кода, в случае нарушения правила, на экран выводится сообщение: 

    Private Sub cmdUpdate_Click() On  Error  GoTo Update_err rs.Edit 
    rs ("Orderld")   =   txtOrder.Text rs.Update 
    Exit   

    Sub Update_err: 
    If  Err.Number  =   3316   Then   '   Нарушение   правила 
   IblError.Caption=  Err.Description rs.Cancel
   Update Exit   
   Sub End   
   If End  Sub 


    70 Поддержание целостности данны, 

    Свойство Description объекта Err содержит значение свойства ValidationText. 
    Отменить текущий метод Edit или AddNew и восстановить текущую запись можно 
с по мощью метода CancelUpdate. Можно либо оставить в форме данные 
пользователя, либ( вернуть в форму текущие данные из базы данных. 

    4.1.2. Ссылочная целостность 

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

    Определение ограничений ссылочной целостности 

    Процессор Microsoft Jet может устанавливать ссылочную целостность в базе 
данных формата Jet. 
    Например, в базе данных Nwind между таблицей Customers (клиенты) и 
таблицей Orders (заказы) определено отношение "один-к-многим" и установлена 
ссылочная целостность. При попытке ввести заказ для несуществующего клиента 
(CustomerlD) или удалить запись клиента, с которой связаны записи заказов, 
возвращается ошибка выполнения. 

    Примечание: Отношения между таблицами можно определять или программным 
способом, используя метод CreateRelation Visual Basic, или вручную, используя 
Microsoft Access. 

    Метод CreateRelation 

    Метод CreateRelation создает новый объект Relation (отношение). Синтаксис метода: 

    Set отношение = 6a3a_dawHb/x.CreateRelation (имя, таблица, 
_внешняя_таблица, атрибуты) 


    Элементы синтаксиса: 

    Элемент	Описание                                                           

    отношение	Объектная   переменная,   представляющая   создаваемый   объект! 
Relation.                                                                      
    база_данных	Объектная переменная, представляющая объект Database, для ко-Ц 
торого создается новый объект Relation.                                        
    имя	Необязательный. String Variant, уникально именующий новый объекЯ 
Relation.                                                                      
    таблица	Необязательный. String Variant, содержащий имя таблицы первичное 
го ключа в отношении. Если в момент создания объекта RelationB такой таблицы 
не существует, возвращается ошибка выполнения.   Ц 
    внешняя_таблица	Необязательный. String Variant, содержащий имя таблицы 
внешнегои ключа в отношении. Если в момент создания объекта Relation такой!! 
таблицы не существует, возвращается ошибка выполнения.            Ц 
    атрибуты	Необязательный. Константа или комбинация констант, содержащаЛ 
информацию относительно типа отношения.                                      Щ 
    Объект Relation предоставляет ядру Microsoft Jet информацию относительно 
отношени между полями двух объектов TableDef или QueryDef. Значение атрибуты 
содержится устанавливается также в свойстве Attributes объектов Field, 
Relation или TableDef. 


    Глава 4. Расширенные возможности программирования доступа	71 


    Каскадные модификации и удаления 

    При установлении ссылочной целостности в параметре атрибуты можно 
специфицировать значение dbRelationUpdateCascade или dbRelationDeleteCascade. 
Если устанавливаются эти опции, процессор базы данных Microsoft Jet позволяет 
пользователю изменять и удалять записи и при этом автоматически изменяет или 
удаляет связанные записи в связанных таблицах. 
    Например, допустим, что создается отношение между таблицами Customers и 
Orders. Если выбирается опция dbRelationDeleteCascad, процессор Microsoft Jet 
будет удалять все связанные записи в таблице Orders всякий раз, когда 
пользователь удаляет запись клиента в таблице Customers. 

    Примечание: Процессор Microsoft Jet при удалении связанных записей не 
выводит на экран никаких предупреждений. Чтобы избежать потерь данных при 
удалении записей, следует четко представлять себе отношения между таблицами, 
определенные в базе данных. 


    Обработка нарушений ссылочной целостности 

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

    Private   Sub   cmdDelete_Click() On   Error   GoTo   Del_Err rs.Delete rs.MoveNext 
    FillFields   '   Процедура   заполнения  данными  полей  формы Exit   Sub 
    lel_Err: 
    '   Нарушения   ограничений  целостности If  Err.Number   =   3200   Then 
IblError.Caption  =  _ 
    "Удалять   клиента   с   заказами  нельзя" Exit   Sub Else 
    '   Обработка  других   ошибок   ... End   If End  Sub 

    Обратите внимание, что здщс^ H^^aj^jj^j^^	не смещается. Текстовые поля в 
форме остаются заполненными текущими данными. 

    4.1.3. Транзакции 

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

    Методы транзакций 

    Методы, связанные с транзакциями, относятся к объекту Workspace. Вызов 
метода Begin-Trans означает начало транзакции. Если на любой из последующих 
модификаций происходит сбой, нужно использовать метод Rollback для отмены всех 
модификаций транзакции. 


    72 Вопросы многопользовательского доступ 

    Если все модификации успешны, вызовом метода Commit!rans нужно 
зафиксировать изме нения в базе данных. В следующем примере транзакция 
создается для добавления вхож дения в таблицы Orders и Order Details: 

    Sub  cmdAddOrder_Click   () 
    On  Error   GoTo  AddOrder_Err 
    DBEngine.Workspaces(0).BeginTrans 
    db.Execute" "TNSERT   INTO  Orders...    .",   dbFailOnError 
    db.Execute   "INSERT   INTO    [Order   Details]...."   ,    dbFailOnError 
    DBEngine.Workspaces(0).CommitTrans 
    IblStatus.Caption  =   "Модификации   завершены" 
    Exit   Sub 
    AddOrder_Err: 
    IblStatus.Caption = Err.Description 
    Msgbox "He все модификации прошли успешно" 
    DBEngine.Workspaces(0).Rollback 
    Exit Sub	"     """  " End Sub 

    Использование транзакций для повышения производительности 

    В дополнение к использованию транзакций для поддержания целостности 
данных, заклю чая в транзакцию оператор SQL UPDATE, можно повышать 
производительность обработв данных. Операции транзакции буферизуются и не 
записываются на диск, пока транзаши! не будет фиксирована.	J ~~ 
    В следующем примере оператор SQL UPDATE заключается в транзакцию: 

    DBEngine.Workspaces(O).BeginTrans 
    '   Увеличить   цену  единицы  на   10% 
    stSQL   =   "UPDATE   Products   SET    [Unit   Price] 
    db.Execute   strSQL,   dbFailOnError 
    DBEngine.Workspaces(0).CommitTrans 
    =   [Unit   Price]    *   0.1' 

    Примечание: Внутри объекта Workspace транзакции могут быть вложенными. 
Прежде чем фиш ровать или аннулировать транзакцию на бол§е.~высоком уровне, 
необходимо проделать дан- • операцию для текущей транзакции. Если требуется, 
чтобы транзакции перекрывались, но ? v независимы от друг друга, нужно создать 
второй объект Workspace. 


    4.2. Вопросы многопользовательского доступа 

    Когда нескольким пользователям позволяется одновременно обращаться к базе 
данн^ >. приложение базы данных становится более сложным. В этом случае 
придется предусмот реть обработку нескольких новых ошибок. Например: 
    •   два пользователя пытаются редактировать одни и те же данные. Ядро базы 
данны) Microsoft Jet автоматически блокирует данные, чтобы предотвратить 
одновременно! редактирование записи двумя пользователями. Если пользователь 
пытается модифици ровать блокированную запись, он получит ошибку выполнения; 
    •   пользователь изменяет запись, которую другой пользователь в этот 
момент про сматривает. Если пользователь пытается модифицировать запись, а 
данные с момент; с    выполнения MeTOflaJEdit изменились, ядро базы данных 
Microsoft Jet вернет ошибку; 
    • ТюльЗоватеНьГудаляет запись, которую другой пользователь 
просматриваетТЕ~сл1 пользователь пытается обратиться к удаленной записи, 
Microsoft Jet вернет ошибку. 
    Ниже описываются эти и другие вопросы многопользовательской работы с данными. 


    Глава 4. Расширенные возможности программирования доступа	73 

    4.2.1. Открытие таблицы в исключительном режиме 

    Чтобы избежать проблем, которые могут возникать, когда несколько 
пользователей имеют возможность обращаться к базе данных, можно открывать 
таблицы для исключительного использования. Открытие таблицы таким образом 
запрещает другим пользователям работать с этой таблицей. Это хотя и довольно 
ограничительное, но в ряде ситуаций — наилучшее решение. 
    Каким образом открывается набор записей, определяет параметр опции метода OpenRecordset. 
    В следующем фрагменте таблица Orders открывается для исключительного 
доступа. Текущий пользователь может изменять таблицу, но другие пользователи 
не могут ни просматривать, ни изменять данные в таблице: 

    Set  recorders   =  dbDbl.OpenRecordset  _ 
    ("Orders",   dbOpenTable,   dbDenyRead  +   dbDenyWrite)	^'?t    f J 
у'f*;." !/&•/• 

    В следующем коде таблица Orders открывается для исключительного доступа 
для записи. Текущий пользователь может изменять и просматривать таблицу; 
другие пользователи могут только просматривать данные в таблице, но не могут 
изменять их: 

    Set  recorders   =  dbDbl .OpenRecordset  _	.'•.•• ("Orders",   
dbOpenTable,   dbDenyWrite)                                                    
           '  ' 

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

    Set  recorders   =   dbDbl.OpenRecordset  _ ("Orders",   dbOpenTable,   dbReadOnly) 

    В следующем примере набор записей открывается в режиме добавления. Текущий 
пользователь может только добавлять записи, но не может просматривать или 
изменять любые существующие записи. На других пользователей данная установка 
не возде_йствует. 

    Set  recorders   =  dbDbl.OpenRecordset  _ 
    ("Orders",   dbOpenDynaset,   dbAppendOnly) 

    Если предполагается только добавлять записи к таблице, для получения 
наивысшей производительности следует использовать опцию dbAppendOnly. Опция 
dbDenyRead доступна только в наборах записей типа table. 

    4.2.2. Блокировка ядра базы данных Microsoft Jet 

    Все системы управления базами данных обеспечивают некоторый механизм 
блокировки, предотвращающий одновременное обновление данных двумя пользователями. 
    Процессор базы данных Microsoft Jet обеспечивает блокировку уровня 
страницы. Страницы — блоки записей размером 2048 байт (2К). Когда Visual Basic 
блокирует страницу, содержащую редактируемую запись, все остальные записи этой 
страницы также будут блокированы. 

    Примечание: Информация в этом разделе касается баз данных, для управления 
которыми используется процессор Microsoft Jet. При обращении к базам данных 
через ODBC применяются механизмы блокировки соответствующей системы управления 
базами данных. 


    Пессимистическая и оптимистическая блокировки 

    Значение свойства LockEdits объекта Recordset определяет, когда 
устанавливается блокировка записи в наборе записей. 


    74 Вопросы многопользовательского доступ 

    Если свойство LockEdits — True, устанавливается пессимистическая 
блокировка. Зэ означает, что страница, содержащая текущую запись, блокируется, 
как только выполняв' метод Edit. Страница разблокируется, когда выполняется 
метод Update. 
    Умолчательная стратегия блокировки предполагает блокирование записи на 
более предо жительный период времени и гарантирует, что, после того как 
выполнен метод Edit, дру| пользователь не может изменить данные. 
    Если свойство LockEdits — False, устанавливается оптимистическая 
блокировка. Стра ца, содержащая запись, блокируется только на время 
модификации записи. 
    Блокировки в этом случае удерживаются более короткий период времени, и 
нескол! пользователей смогут использовать метод Edit без блокирования 
страницы. Однако, ее используется оптимистическая блокировка, усложняются 
механизмы управления возм< ными ошибками, когда пользователь выполняет метод Update. 
    Если частых попыток изменения одной записи несколькими пользователями не 
предвид ся, рекомендуется установить LockEdits в False. 

    Разблокирование 

    Ядро базы данных Microsoft Jet отмечает страницу, которую нужно 
разблокировать.1 только модификация будет закончена. Однако, блокировки 
не.удаляются, пока полис не выполнены другие действия. 
    Используя метод Idle объекта DBEngine с опцией dbFreeLocks, можно 
приостановит^ Лютку и позволить процессору Microsoft Jet освободить 
блокиро?кй~и подхватить в фон режиме другие задачи. Это делается следующим образом: 

    DBEngine.Idle  dbFreeLocks 


    4.2.3. Обработка ошибок блокировки 

    Когда несколько пользователей модифицируют базу данных, необходимо 
предусмотри код обработки следующих ошибок: 
    3260   Couldn't update; currently locked (модификация невозможна по 
причине блокировк» Происходит при вызове метода Edit, когда текущая запись уже 
блокирована. В ко/ следует на короткое время сделать паузу и затем вызвать 
Edit снова или сообщит! пользователю относительно ошибки. 
    3186   Couldn't save; currently locked (сохранение невозможно по причине 
блокировки). Пр исходит при оптимистической блокировке при вызове метода 
Update, когда текуща запись блокирована. В коде следует на короткое время 
сделать паузу и зате вызвать Update снова или сообщить пользователю 
относительно ошибки. 
    3197   Data has changed; operation stopped (данные изменились; операция 
остановле Происходит при вызове метода Edit или Update, если другой 
пользователь изме^ данные с момента последнего обращения к ним текущего 
пользователя. В следует обновить форму последними данными или информировать 
пользоват относительно ошибки. 

    Обработка ошибок при выполнении метода Edit 

    В следующем примере обрабатываются ошибки блокировки, которые могут 
происходит при выполнении метода Edit: 

    Private  Sub  cmdEdit_Click() On  Error  GoTo   HandleError rs.Edit 


    Глава 4. Расширенные возможности программирования доступа	75 

    ButJ^nEditAddMode Exit   Sub	( 
    HandleError: 
    Select   
    Case   Err.Number 
    Err   
    Select  Case   .Number 
    Case   3260   '   Текущая   страница  блокирована 
    MsgBox   "Запись в данный момент блокирована. Попытайтесь   еще  раз" 
    Case   3197   '   Данные  изменились 
    MsgBox   "Данные  изменились   и  будут   обновлены" 
    rs.Bookmark  =   rs.Bookma,rk 'Полунщчь   обновленные  данные 
    "FTllFields   '   Заполнить   поля  данными
    rs.Edit 
    Case  Else 
    MsgBox  Err.Number   &   
    ":"   &   
    Err.Description 
    End  Select 
    End  Sub 

    В вышеприведенном примере, если запись блокирована, когда пользователь 
выполняет метод Edit, выводится сообщение. Если данные изменились, код 
регенерирует форму последними данными. 

    OnepSTOgjecOrders.bookmark = recorders.bookmark регенерирует текущую 
запись в наборе -У записей последними данными йз'базы данных. 

    Обработка ошибок при выполнении метода Update 

    В следующем примере обрабатываются ошибки, которые могут происходить при 
выполнении оператора Update: 

    Private Sub cmdSave_Click() Dim answer As Integer On Error GoTo HandleError 
    rs.Fields("Category Name") = txtCategoryName.Text 
    rs.Fields("Description") = txtDescription.Text rs.Update 
    rs. Bookmark = rs.LastModJJg-ied "FiTTFigia'S———'——— ButtonNavigateMode 
    'Exit Sub
    HandleError: 
    Select 
    Case Err.Number 
    Case 3260 
    MsgBox " Текущая запись блокирована. " & _ 
    "Попытайтесь сохранить еще раз позже или отмените изменения." 
    Case 3197 
    answer = MsgBox ("Данные были изменены другим пользователем. " & 
    " Перезаписать изменения? ", vbYesNo) 
     If answer = vbYes Then Resume 
     Else rs.Bookmark = rs.Bookmark ' Обновить запись изменениями 
     ' других пользователей 
     cmdCancel_Click 
     End If 
     Case Else 2 


    76 Работа с внешними данными 

    MsgBox Err.Number & End Select End Sub 
    " & Err.Description 

    Обработка ошибок при удалении записей другими пользователями 

    Если другой пользователь удаляет запись из базы данных и набор записей 
типа dynaset полностью заполнен, указатель на запись не будет удален из набора. 
    Однако удаленной записи больше нет в базе данных — ее нельзя просмотр_еть, 
и при попытке обращения к данным этой записи произойдет ошибка.     '   Г——""~ 
    Самый простой способ обработать эту ошибку — удалить вхождение, которое 
указывает на удаленную запись набора dynaset.	"    ~~          •——••-
    В следующем фрагменте показано, как управлять ошибкой, сгенерированной 
попыткой обратиться к удаленной записи: 

    Private Sub cmdMoveFirst_Click() 
    On Error GoTo Err_Movefirst: \r»retry_MoveFirst: rs.MoveFirst 
    txtLName.Text = rs("Last Name") ' Exit Sub Err_Movefirst: 
    If Err.Number = 3167 Then 
    ' Запись удалена, значит нужно ' удалить ^хождение из dynaset rs . Delete  
      "*' Resume retry_MoveFirst Els'e 
    MsgBox Err.Description Exit Sub End If End Sub 

    Может произойти ошибка 

    4.3. Работа с внешними данными 

    Visual Basic позволяет обращаться к нескольким базам данных 
индексно-последовательно-го представления (ISAM), таким, как dBASE, Paradox и 
Microsoft Visual FoxPro. Для таких баз данных Visual Basic обеспечивает 
драйверы ISAM. 
    Visual Basic можно также использовать для обращений к стандартным файлам 
данных, например к текстовым файлам с разделителями. 

    Примечание: Базы данных, для управления которыми используется процессор 
базы данных Microsoft Jet, рассматриваются как внутренние базы данных Visual Basic. 

    В этом разделе описывается, как обратиться с помощью Visual Basic к 
внешним данным, включая базы данных ISAM и стандартные файлы данных. 

    4.3.1. Способы доступа к данным 

    К данным во внешней базе данных можно обратиться либо присоединяя внешнюю 
базу данных, либо открывая ее непосредственно. 


    Глава 4. Расширенные возможности программирования доступа 77 


    Присоединение таблицы базы данных Microsoft Jet 

    Когда внешняя база данных присоединена к базе данных Microsoft Jet, данные 
таблицы остаются во внешней_базе данных. Однако информация соединения и 
определение таблицы сохраняются в базе данных Microsoft Jet. Таблицу можно 
использовать, как если бы это была любая другая таблица базы данных Microsoft 
Jet, за исключением того, что для присоединенной табгшцы нельзя создавать 
.набор.записей типа table. 
    Присоединение таблицы к базе данных Microsoft Jet можно выполнить с 
помощью простой процедуры в Microsoft Access. Присоединить таблицу можно также 
программным способом, используя метод CreateTableDef Visual Basic. 
    Синтаксис метода CreateTableDef следующий: 

    Se( o6beKm_TableDef = база_данных.Сгеа\.еТаЬ\еОеЦимя, атрибуты, источник, соединение)	~ 

    Элементы метода: 
    Элемент	Описание 
    o6beKm_TableDef	Объектная   переменная,   представляющая   создаваемый   
объект TableDef. 
    6аза_данных	Объектная переменная, представляющая объект Database, 
используемый для создания нового объекта TableDef. 
    имя	Необязательный. Значение String Variant, уникально именующее новый 
объект TableDef. 
    атрибуты	Необязательный. Константа или комбинация констант, представляющая 
одну или больше характеристик нового объекта TableDef. 
    источник	Необязательный. Значение String Variant, содержащее имя таблицы 
внешней базы данных — оригинального источника данных. Строка источник 
становится установкой свойства нового объекта TableDef. 
    соединение	Необязательный. Значение String Variant, содержащее информацию 
о внешней базе данных или присоединенной таблице. 
    ? 

    Примечание: Обычно обращение к данным в таблицах ODBC, присоединенных к 
базе данных Microsoft Jet, еь/полняется_более_быстро,_чем при их 
непосредственном^ открытии, так как информация соединения кэиящуЁ{пся_гщи 
открытии базы "данных Microsoft Jet. По этой причине, когда возможно, следует 
присоединять внешние таблицы вместо их непосредственного открытия. 

    Открытие таблицы 

    При непосредственном открытии внешней таблицы необходимо специфицировать 
информацию соединения, используя параметры метода OpenDatabase или свойство 
Connect элемента управления Data. 
    В следующем фрагменте для открытия таблицы используются методы 
OpenDatabase и OpenRecordset: 

    Sub  OpenTable () 
    Dim wspCurrent  As  Workspace Dim dbCurrent  As   Database Dim  
rstProducts  As   Recordset 
    Set  wspCurrent  =  CreateWorkspace ("New Workspace",   "Admin",   "",   _ 
    dbUseJet)	9 Set dbCurrent = wspCurrent.OpenDatabase("C:\VB\Nwind. mdb") f 
Set rstProducts = dbCurrent.OpenRecordset("Products", dbOpenTable) 


    78 Работа с внешними данным. 

    rstProducts.MoveLast 
    MsgBox "В таблице " & rstProducts.RecordCount & " записей" 
    rstProducts.Close dbCurrent.Close wspCurrent.Close 
    End Sub 

    4.3.2. Работа с базами данных ISAM 

    Чтобы непосредственно .открыть базу данных ISAM, нужно установить в 
качестве параме 6аза_данных метода OpenDatabase (или свойства DatabaseName 
элемента управле! Data) имя папки, которая содержит таблицы ISAM. Для имени 
базы данных можно испо зовать также сетевой путь (например, \\server1\share1). 
    В свойстве Connect объекта Database или элемента управления Data нужно 
указать • открываемой базы данных. Список возможных значений свойства Connect 
для внешних f данных ISAM приводится в следующей таблице: 

    Тип базы данных	Спецификатор	Пример                           .    | 

    База данных Microsoft Jet	[база_данных];	диск:\путь\имя_файла.гтга'Ь | 
    dBASE III	dBASE III;	дискЛпуть                             Щ 
    dBASE IV	dBASE IV;	дискЛпуть                            | 
    dBASE 5	dBASE 5.0;	диск:\путь                            Щ 
    Paradox 3.x	Paradox 3.x;	дискЛпуть                             Ц 
    Paradox 4.x	Paradox 4.x;	дискЛпуть                             щ 
    Paradox 5.x	Paradox 5.х;,диск:\путь, 
    FoxPro 2.0	FoxPro 2.0;	дискЛпуть                            !Д 
    FoxPro 2.5	FoxPro 2.5;	дискЛпуть                             ^ 
    FoxPro 2.6	FoxPro 2.6;	дискЛпуть                             Ц 
    Excel 3.0	Excel 3.0;	диск:\путь\имя_файла.х!з    Щ 
    Excel 4.0	Excel 4.0;	диск:\путь\имя_файла.х1з    | 
    Excel 5.0 or Excel 95	Excel 5.0;	диск:\путь\ имя_файла.х!з   Щ 
    Excel 97	Excel 97;	диск:\путь\ имя_файла.х!з   | 
    HTML Import	HTML Import;	диск:\путь\ имя_файла        • 
    HTML Export	HTML Export;	дискЛпуть                             'Щ 
    Text	Text;	дискЛпуть                             Щ 

    В следующем примере открывается база данных Microsoft Visual FoxPro: 

    Public   Sub  OpenFoxProTable () Dim  dbFox  As   Database Dim  
recAccounts  As   Recordset Set   dbFox  =  OpenDatabase  __ 
    ("\\FoxPro\Data\AP",   False,   False,   _ "FoxPro   5.0;") 
    Set   recAccounts   =  dbFox.OpenRecordset("Accounts") End  Sub 


    Глава 4. Расширенные возможности программирования доступа	79 

    Чтобы присоединить базу данных ISAM к существующей базе данных .mdb, 
необходимо создать новый объект TableDef и установить свойства Connect и 
SourceTableName объекта TableDef. 
    В следующем примере ^базе данных Microsoft Jet присоединяется таблица 
Visual FoxPro. Можно либо создать новую базу flaHHbix_Mi?rosof^Jet, либо 
использовать существующую: 

    Dim  tbdAttach  as   TableDef 
    Set  dbDbl=OpenDatabase   ("Dbl.mdb") 
    Set   tbdAttach  =  dbDbl.CreateTableDef    ("Attached  FoxPro  Table") 
    tbdAttach.Connect   =   "FoxPro~5T6;DATABASE=\\FoxPro\AP" 
    tbdAttach.SourceTableName  =   "Accounts" 
    dbDbl.TableDefs.Append tbdAttach 

    Досле присоединения таблицы к базе данных Microsoft Jet ее можно открыть, 
используя Следующий код: 

    Set  dbDbl   =  OpenDatabase   ("Dbl.mdb") 
    Set   recAttach  =  dbDbl.OpenRecordset    ("Attached  FoxPro   Table") 


    4.3.3. Работа с файлами данных 

    Приложение Visual Basic, кроме информации базы данных, может работать с 
данными из стандартных файлов. 
    При работе с информацией из стандартных файлов данных можно использовать 
следующие механизмы: 
    • операторы файлового ввода-вывода — Open, Get, Put, Input #, Print #, 
Write #; 
    •  импорт данных в базу данных вручную. Импортировать текстовый файл в 
базу данных можно с помощью Microsoft Access. Microsoft Access поддерживает 
различные форматы файлов, такие, как файлы фиксированной длины, разграниченные 
запятой и так далее; 
    •  импорт данных в базу данных программным способом. Можно создать 
программный код, который будет читать текстовый файл и затем добавлять данные 
в базу данных. 
    В следующем фрагменте показаны базовые шаги использования файлового 
ввода-вывода для чтения файла и сохранения информации в базе данных: 

    Private Sub Commandl_Click() Dim fhandle As Integer f handle = FreeFileO 
    Open "TextFilel" For Input As fhandle Do 

    ' Прочитать файл одним из операторов ввода 
    ' Сформировать строку SQL 
    ' Выполнить оператор SQL INSERT Loop Until EOF(fhandle) End Sub 

    4.4. Работа с базами данных ODBC 

    В ОАО версии 3.5 представлена новая технология доступа клиент/сервер — 
ODBCDirgct. С помощью этой технологии соединение с источником данных ODBC 
устанавливается с использованием механизмов объектов доступа к данным без 
привлечения процессора Microsoft Jet. 


    80 Работа с базами данных ODBC 

    4.4.1. Определение рабочей области ODBCDirect 

    Первый шаг при использовании ODBCDirect состоит в определении типа рабочей 
области Здесь имеется две возможности: установить умолчательный тип рабочей 
области либо определить рабочую область ODBCDirect. 

    Установка умолчательной рабочей области 

    Чтобы установить умолчательный тип рабочей области как ODBCDirect, следует 
использовать свойство DefaultType объекта DBEngine. Для этого свойства нужно 
определить значение dbUseODBC. Этот тип рабочей области будет затем 
использоваться всякий раз при создании объекта Workspace. Эта установка 
предотвращает загрузку в память ядра базы flajHjjbj^jyiicrosqft Jet (при 
условйй7что~до этого еще не была создана рабочая область базы данных Microsoft Jet). 
    В следующем примере устанавливается умолчательный тип рабочей области ODBCDirect: 

    DBEngine.DefaultType = dbUseODBC 


    Создание конкретной рабочей области 

    Умолчательную рабочую область можно переопределять, используя параметр тип 
метода CreateWorkspace. Например, ниже создается рабочая область ODBCDirect: 

    Dim  wspODBC  As  Workspace 
    Set  wspODBC  =  DBEngine.CreateWorkspace  _ 
    ("NewODBCWorkspace",    "Admin",    "",   dbUseODBC) 


    4.4.2. Соединение с удаленным источником данных 

    Соединение с удаленным источником данных подобно открытию базы данных 
Microsoft Jet. Сначала создается рабочая область (например, рабочая область 
ODBCDirect), а затем открывается источник данных. 
    Для открытия удаленного источника данных создается объект Connection, 
точно так же, как для открытия базы данных Microsoft Jet создается объект 
Database. После создания соединения из удаленного источника данных можно 
отбирать информацию. 

    Объявление соединения 

    Объектная переменная типа Connection содержит информацию соединения. 
Открыть соединение можно с помощью оператора Set. 
    В следующем примере соединение открывается в умолчательной рабочей области: 

    Dim conNewConnection As Connection 
    Set conNewConnection = OpenConnection _ 
    ("New", dbDriverPrompt, false, _ 
    "ODBC;DATABASE=pubs;UID=sa;PWD;DSN=SQLServer") 

    Синтаксис метода OpenConnection: 

    Set соединение = рабочая_область.OpenConnection (имя, опции, 
только_для_чтения, строка_соединения) 

    В следующей таблице описывается использование элементов метода OpenConnection: 

    Элемент	Описание 
    соединение	Объектная переменная типа Connection, ассоциированная с новым соединением. 


    Глава 4. Расширенные возможности программирования доступа 81 

    Элемент	Описание 

    Рабочая_область	Необязательный. Объектная переменная типа Workspace, 
указывающая на существующий объект Workspace, который будет содержать новое соединение. 
    Имя	Любая строка, если зарегистрированное имя источника данных ODBC (DSN) 
специфицируется ^параметре строка_сое^инения. Это имя будет также свойством 
Name объекта Connection. Если допустимое имя DSN не включено в параметр 
строка_соедине-ния, имя должно содержать допустимое ODBC DSN, которое будет 
также свойством Name объекта Connection. 
    опции	Устанавливает различные опции для соединения. Определяет, запросить 
ли и когда запросить пользователя установить соединение и открыть ли 
соединение асинхронно. 
    только_для_чтения	True или False. Если True, модификации при работе в 
соединении не допускаются. Значение по умолчанию — False. 
    строка_соединения	Строка соединения ODBC.                                  

    В следующей таблице перечисляются значения и использование параметра опции: 

    Константа	Результат 

    dbDriverNoPrompt	ODBC Driver Manager использует строку соединения, обеспечиваемую 
    в параметре строка_соедиЛёЙШ7 
    dbDriverPrompt	ODBC Driver Manager выводит на экран окно диалога ODBC Data 
Sources, в котором представлена"инф"ор1\лация из параметра строка_соединения. 
Строка соединения формируется из выбираемого пользователем DSN или, если 
пользователь не специфицирует DSN, будет использоваться умолчательное имя DSN. 
    dbDriverComplete	Если параметр строка_соединения включает всю необходимую 
информацию для установления соединения, ODBC Driver Manager использует строку 
в параметре строка_соединения. Иначе он ведет себя так, как если бы была 
специфицирована умолчательная константа dbDriverPrompt. Это — значение по умолчанию. 
    dbDriverComplete-Required	Эта опция ведет себя подобно константе 
dbDriverComplete, за исключением того, что драйвер ODBC деактивирует подсказки 
для любой информации, не требуемой для установки соединения. 
    dbRunAsync	Выполнение методадсинхронно. Эта константа может использоваться 
с любой другой константой опции. 

    4.4.3. Отбор удаленных данных 

    Процедура получения удаленных данных с использованием ODBCDirect 
подобыа-ОТ.бдру да>|ных_изДазы flaHH^b]x_MjcjrosofUet. После установления с 
помощью ODBCDirect соединения с базой данных ODBC методом OpenRecordset 
необходимо создать объект Recordset — точно так же, как это делается при 
получении записей из базы данных Microsoft Jet. 
    В следующем примере создается рабочая область ODBCDirect и далее в ней 
создается набор записей для данных из базы данных SQL Server: 

    Sub  OpenODBCDirectRecordset() 
    Dim  wspODBC  As   Workspace 
    Dim  conODBC  As   Connection 


    82 Вопросы производительном 


    Dim  rstODBC  As   Recordset 
    Set  wspODBC  =  CreateWorkspace  _ 
    ("",   "sa",    "",   dbUseODBC) Set   conODBC  =  wspODBC.OpenConnection  _ 
    ("NewConncetion",   dbDriverNoPrompt,   False,   _ 
    "ODBC;DATABASE=pubs;UID=sa;PWD=;DSN=SQLServer") Set   rstODBC  =   
conODBC.OpenRecordset  _ 
    ("SELECT   *   FROM  authors  WHERE   au_lname  =   'Green'",   _ 
    dbOpenSnapshot,   0,   dbReadOnly) rstODBC.MoveLast MsgBox   "   Этот  
удаленный  набор  записей  содержит   "   &  _ 
    rstODBC.RecordCount   &   "   записей." 
    rstODBC.Close conODBC.Close 
    wspODBC.Close 
    End  Sub 

    Набор записей, отбираемый из удаленного источника данных может управляться 
тем Ж( способом, что и наборы записей, создаваемые через ОАО процессором 
Microsoft Jel Дополнительную информацию см. в главе 3. 

    Метод Open Recordset в рабочей области ODBCDirect 

    'Ниже приводятся параметры метода OpenRecordset, доступные при 
использовании рабочей области ODBCDirect: 
    Тип 
    dbOpenDynamic	Открывает набор записей типа dynamic, который можно 
использовать для добавления, изменения или удаления записей из исходной 
таблицы или таблиц базы данных. Набор типа dynamic может содержать поля из 
одной или больше таблиц базы данных. 
    Опции 
    dbRunAsync	Выполняет асинхронный запрос. Примечание: Асинхронный запрос — 
тип запроса, при выполнении которо
    го результаты запроса возвращаются немедленно, без перехода запроса в 
отложенное состояние. Это позволяет приложению продолжать параллельно другую обработку. 
    Блокировки 
    dbOptimisticValue	Используется оптимистический параллелизм, основанный на 
значениях записей. 
    dbOptimisticBatch	Активирует пакетное оптимистическое обновление. 
    Примечание: Умолчательная рабочая область ODBCDirect — только для чтения. 
Чтобы дать возможность пользователям читать и записывать данные в рабочей 
области ODBCDirect, необходимо специфицировать тип блокировки dbOptimistic. 

    4.5. Вопросы производительности 

    Структура и содержание-кода доступа к данным приложения существенно влияет 
на производительность. При создании приложения базы данных рекомендуется 
учитывать следующие рекомендации: 


    Глава 4. Расширенные возможности программирования доступа	83 

    •  знать организацию запрашиваемых данных. Некоторые запросы SQL более 
эффективны, нежели другие. Например, сортировка по полю, которое содержит 
индекс, выполняется быстрее, чем по полю, для которого индекс не создан; 
    •  запрашивать только необходимые данные. Следует избегать создавать 
наборы записей типа dynaset и зпарзЬо1_для_полной таблицы. В проекте 
приложения должны быть предусмотрены запросы к пользователю НГГввод критериев 
поиска. В этом случае будут возвращаться prpa|j^eHjHbj^ejj^a6pp_bi записей и 
приложение будет работать быстрее; 
    •   вместо выбора всех столбцов в записи отбирать только необходимые 
столбцы. В следующем фрагменте создается набор записей, основанный на 
значении, введенном пользователем. Например, если пользователь вводит "А", 
создается набор записей всех служащих, фамилия которых начинается с "А": 

    strSQL = "SELECT [LastName], [FirstName] FROM Employees   "   &   _ 
    "WHERE    [LastName]    Like   "   & 
    "'"   &   txtName.text   &   '""   &   
    "*"   ' Критерий берется из поля формы 
    Set   recEmployees   =  dbDbl.OpenRecordset    (strSQL,dbOpenDynaset) 

    •   использовать только требуемые функциональные возможности. Если 
модифицировать базу данных не предполагается, ее следует открывать только для 
чтения. Это повышает производительность, так как в этом случае процессор базы 
данных Microsoft Jet не должен управлять блокировками. 
    Если не требуется изменять набор записей, его также нужно открывать только 
для чтения. Если предполагается только добавлять записи к набору, следует 
открывать его с опцией dbAppendOnly; 
    •   использование транзакций. Использование транзакций уменьшает 
интенсивность дискового доступа — ввод-вывод выполняется, в среднем, один раз 
на транзакцию, вместо одного раза на запись. Это может значительно повысить 
производительность приложения; 
    •   использование сохраненных запросов. Обычно лучше создавать сохраненные 
запросы, нежели использовать операторы SQL в тексте. Сохраненный запрос 
прекомпилиру-ется, что исключает фазу компиляции в период выполнения. Кроме 
того, часто проще сопровождать запросы, которые сохранены в файле .mdb, а не 
описаны в тексте кода. Если возможно, следует использовать сохраненные запросы 
или операторы SQL для пакетных операции, таких, как модификация группы 
записей, вместо модификации запи-" сей по одной методом Update; 
    •   присоединение таблиц. Рекомендуется, когда возможно, присоединять 
таблицы базы данных ODBC к локальной базе данных .mdb. Определение данных и 
информация соединения поддерживаются в файле .mdb, что, следовательно, 
повышает производительность приложения. 


    84 Конфигурирование Crystal Reports 

    Глава 5.   Создание отчетов с помощью Crystal Reports 

    Конечной целью многих приложений является получение твердых копий 
документов, в том или ином виде отображающих данные. Это могут быть таблицы, 
формы данных, рабочие или стандартные документы — счета-фактуры, ведомости, 
инвентарные листы и т. д.. Получать такие документы позволяют специальные 
программы — генераторы отчетов. В том или ином виде функции генератора отчетов 
реализованы во всех инструментальных средствах, предназначенных для работы с 
данными. Имеется такой инструмент и в Visual Basic. 
    В комплекте с Visual Basic 5.0 поставляется процессор отчетов Crystal 
Reports 4.6 разработки Seagate Software. Тот факт, что эта программа уже на 
протяжении нескольких версий включается в комплект поставки Microsoft Visual 
Basic (а^кже_о.р_одуктов других производителей, например Borland Visual 
dBase и др.), говорит о ее несомненном качестве и широких ВОЗМОЖНОСТЯХ'. " * 
    Crystal Reports для Visual Basic — полнофункциональная среда, позволяющая 
создавать отчеты многих стилей и любой сложности из данных локальных файлов 
.mdb и сетевых баз данных SQL/ODBC, с широкими возможностями форматирования 
представляемой информации — как вручную, так и программным способом в коде 
Visual Basic. 

    Ц Crystal Reports Pro - [Untitled Report «II 
    -l.PI.xl 
    Л1 file   Edit   insert   Format   ?>atabase   Fjepoft   Window   
Help	-Jfl] x| 
    ~I\ 
    Design j Preview | 
    Today 18:45     Close ] 
    Ш( 
    !П.  i . li 
    .   fr.   ,   .   IB   i  .   IU 
    Title 
    Page header 
    «Г ...."     l               >Г	Au 
    tti:AtUD-A ±LJ			Insert 1   Done j    ESrowse Field Data...	/ 
    1               d	ПЗ	jd-J':	гшшаи in _	5Ш 

    Рис. 5.1. Рабочий экран Crystal Reports. 


    5.1. Конфигурирование Crystal Reports 

    Crystal Reports позволяет настраивать многие из умолчательных установок 
программы, наилучшим образом конфигурируя ее под потребности разработчика. Эти 
установки воздействуют на такие аспекты: 

