> ## Redes - Programas Multiusuários

##### Conteúdo

- Introdução
- O acesso aos Dados
- Bloqueio de Registros

### Introdução.

    Mesmo que você não desenvolva sistemas para um ambiente de rede, precisa saber
    alguns conceitos relativos ao assunto.

    Naturalmente o Visual Basic fornece acesso compartilhado ao banco de dados do
    sistema e vários usuários poderão acessar  os dados ao  mesmo tempo; o  VB faz o
    bloqueio e o desbloqueio das páginas dos dados quando necessário, automaticamente.

    Se você quiser que os dados de sua aplicação sejam acessados por um único usuário,
    este é o modo exclusivo , terá que informar isto ao VB.

    Para abrir um arquivo de dados no VB usamos o método OpenDatabase, vejamos então
    sua sintaxe:

    Set database = workspace.OpenDatabase(dbname[, exclusive[, read-only[, source]]]

    Observe o argumento opcional exclusive , ele pode assumir dois valores:

    -True   -  Abre o arquivo no modo exclusivo , ou seja , não compartilhado.
    -False  -  Abre o arquivo no modo compartilhado.

    Se você omitir este argumento o arquivo é aberto no modo compartilhado.

    O argumento read-only também pode assumer dois valores:

    -True  - Abre o arquivo no modo read-only , isto é, somente leitura.
    -False - Abre o arquivo no modo read/write , isto é , leitura e escrita.

    Se voce omitir este argumento o arquivo é aberto no modo leitura e escrita.

    Portanto se você usa a seguinte sintaxe para abrir um banco de dados do seu
    sistema:

    dim db as database
    set db = dbengine.workspaces(0).OpenDatabase(app.path & "\nome_arquivo")

    O seu arquivo estará sendo aberto no modo compartilhado. Até aqui tudo bem !

Conteúdo

### O acesso aos Dados.

    O limite mais restritivo que podemos impor a um banco de dados é sua abertura
    em modo exclusivo.

    Isto impedirá que qualquer usuário tenha acesso ao banco de dados enquanto ele
    estiver sendo utilizado.(Isto inclui todas as suas tabelas e consultas.)

    Vejamos a sintaxe utilizada para este caso:

    dim db as database
    set db = dbengine.workspaces(0).OpenDatabase(app.path & "\nome_arquivo",True)

    A tentativa de abrir o arquivo em uso irá gerar uma mensagem de erro pelo VB.

    Quer algumas boas razões para usar o  acesso exclusivo ?

    Use-o em operações que afetem todo o banco de dados tais como:

    -Compactação do banco de dados
    -Atualização de tabelas inteiras
    -Alteração da estrutura do banco de dados(inclusão de tabelas, índices, etc...)

    Se você não quiser ser tão radical, pode restringir o acesso á tabela em
    uso pelo seu sistema.

    Para fazer isto utilizamos as opções do método OpenRecordSet para negar
    acesso de leitura e/ou gravação ás tabelas , vamos a sua sintaxe:

    Set variable = database.OpenRecordset(source[, type[, options]])

    Vejamos as opções mais usadas:

    -dbDenyRead    Impede os usuários de examinar os dados contidos na tabela,até você fechá-la.
                   (Disponível para recordsets do tipo tabela)

                   Você usuará esta opção quando for necessário atualizar informações na tabela inteira.

                   Ex: Dim db as database,rs as recordset
                       set rs=db.openrecordset("nome_tabela",DbOpenTable,dbDenyRead)

    -dbDenyWrite   Os usuários podem visualizar os dados mas não podem atualizar as informações da tabela,
                   nem incluir novos registros ,até você fechá-la.(Válido para Tabelas,Dynasets e Snapshot)

                   Você pode usar esta opção quando estiver incluindo novos registros na tabela e não
                   houvesse modificações nos registros existentes.

                   Ex: Dim db as database,rs as recordset
                       set rs=db.openrecordset("nome_tabela",DbOpenTable,dbDenyWrite)

    -dbReadOnly    Permite somente visualizar os dados da tabela.
                   Ex: Dim db as database,rs as recordset
                       set rs=db.openrecordset("nome_tabela",DbOpenTable,dbReadOnly)

                   Você pode usar esta opção em tabelas de pesquisa.

                   Uma outra maneira de restringir o acesso a apenas leitura , é utilizar
                   Snapshots.Eles sempre são de somente leitura.
                   A vantagem dos Snapshots é que eles ficam armazenados na memória.
                   Ex: Dim db as database,rs as recordset
                       set rs=db.openrecordset("nome_tabela",DbOpenSnapshot)

    -dbAppendOnly  Permite somente a inclusão de novos registros(Válido somente para dynaset)
                   Ex: Dim db as database,rs as recordset
                       set rs=db.openrecordset("nome_tabela",DbOpenDynaset,dbAppendOnly)

    Se você tentar abrir qualquer tabela com as restricões acima mencionadas e um outro
    usuário já estiver com ela aberta ocorrerá uma mensagem de erro.

    Dai conclui-se que o código de tratamento de erros deverá ser utilizado em todos
    os lugares onde o método OpenRecordset for utilizado, pois neste caso o método
    falhará e você tem que estar preparado para interceptar o erro gerado.

    Que tal provarmos tudo isso ? Então vamos lá...

    -Primeiro vejamos um exemplo para o caso da abertura do banco de dados nos modos
     exclusivo e compartilhado :
     - Acesso Exclusivo/Compartilhado.

    -A seguir um exemplo que analisa o comportamento do Jet na abertura das tabelas
     nas  opções dbDenyRead , dbDenyWrite e dbReadOnly :
     - Acesso as tabelas - dbDenyRead , dbDenyWrite e dbReadOnly

    Nota :Da mesma forma você pode usar as opções descritas acima para criar um dynaset.
          Ex: Para criar um dynaset com a opção dbDenyWrite

    Set rs = db. OpenRecordset("SELECT * FROM Tabela", DbOpenDynaset, dbDenyWrite)

Conteúdo

### Bloqueio de Registros

    Se sua aplicação for rodar em um ambiente multiusuário mais cedo ou mais tarde
    alguém tentará atualizar um registro que está bloqueado por outro usuário ou
    outro usuário tentará modificar um registro que você esta atualizando. E ai...?

    Antes de fazer um pedido para editar um registro já existente ou incluir um novo
    registro,  o Jet irá verificar se nenhum outro usuário esta tentando modificar o
    registro ou acrescentando um registro novo , para isso o Jet utiliza a técnica de
    bloqueio de registros.

    Mas atenção , o jet na não aceita o bloqueio de registros , na verdade o que
    ocorre é o bloqueio da página ou páginas contendo o registro. Como uma
    página contém 2K (2048 bytes), o bloqueio será efetuado não somente no registro
    desejado mas também nos adjacentes , a não ser que o registro tenha exatamente o
    tamanho de 2048 bytes.

    O jet trabalha então com dois métodos de bloqueios : o pessimista e  o otimista.
    Vejamos cada um deles:

    1-Bloqueio pessimista(O padrão usado pelo VB)

     Executa o bloqueio da página que contém o registro no momento que sua aplicação
     executar o método Edit

     O registro permanecerá bloqueado até ser executado o método Update e os dados
     forem gravados no arquivo.

     Perceba que enquanto você estiver editando o registro outros usuários não poderão
     alterá-lo. Se alguém tentar bloquear a página que contém o registro o Jet retornára
     um erro.

     A desvantagem do bloqueio pessimista é que se você bloquear o registro para edição
     por um período longo , ninguém mais conseguiria editar o mesmo registro e os outros
     registros da mesma página além de afetar o desempenho do sistema.

    2-Bloqueio otimista

     Executa o bloqueio da página contendo um determinado registro somente quando for
     invocado o  método Update.

     O bloqueio é imediatamente liberado quando se completa a operação de atualização.

     A vantagem é que a página é bloqueada por um curto período de tempo.

     A desvantagem é a possibilidade de outro usuário alterar os dados contidos no
     registro entre os instantes em que são empregados os métodos Edit e  Update,
     se isto ocorrer o Jet retorna um erro.

    Com isto em mente você deve levar em conta algumas considerações ao utilizar o bloqueio
    de registros. Vejamos :

    1-O que fazer caso não seja possível bloquear um registro.
    2-Como evitar que o usuário mantenha um registro bloqueado por muito tempo.
    3-Determinar qual tipo de bloqueio usar: pessimista ou otimista

    No primeiro caso temos os conflitos de bloqueio, ou seja, se um usuário
    bloqueou um registro e outro usuário requisitou um bloqueio no mesmo registro
    ocorrá um erro.

    Como o VB não fornece uma maneira de verificar se um registro está bloqueado,
    você tem que estar preparado para os erros de bloqueio implementando um código
    de tratamento de erros em todos os lugares onde irá acrescentar ou atualizar os
    registros.

    Dentre os inúmeros erros que o Jet retorna em ambiente multiusuário existem 3 que
    são muito importantes e deles você deve se proteger,  vejamos :

    -Erro 3167 - O registro foi deletado

                 Lembre-se que as modificações(alterações,exclusões,etc..) feitas
                 em um registro somente serão refetidas em um dynaset quando
                 o VB reler a página que contém o registro.

                 Neste caso o erro ocorre quando você tentar executar o método
                 Edit em um registro que já foi deletado por outro usuário
                 desde a última vez que você leu a página.

    -Erro 3197 - Os dados foram modificados; a operação foi interrompida.
                 Ocorre quando você tenta editar um registro que sofreu modificações
                 por outro usuário desde a ultima vez que você leu a página.

    -Erro 3260 - Impossível atualizar; atualmente bloqueado pelo usuário x
                 na máquina y.
                 Ocorre quando você tenta bloquear uma página que já está bloqueada
                 por outro usuário.

    Quanto ao método de bloqueio a utilizar , na maior parte dos aplicativos de banco
    de dados, o bloqueio otimista é a melhor opção , mas existirão situações em que
    você deverá usar o bloqueio pessimista.

    Para estabelecer o método de bloqueio de registro, defina a propriedade LockEdits
    da tabela ou do dynaset com que está trabalhando. Assim :

    1-Produzir bloqueio Pessimista - LockEdits = True

      Dim rs as Recordset
      rs.LockEdits = True

    1-Produzir bloqueio Otimista - LockEdits = False

      Dim rs as Recordset
      rs.LockEdits = False

    Como dissemos a liberação do bloqueio é automática, mas em aplicativos com intensa
    entrada de dados você pode precisar fazer pausas momentâneas no processamento do
    aplicativo para permitir ao Jet realizar o seu trabalho de manutenção; para isto
    utilizar o método Idle, da seguinte forma:

     DbEngine.Idle dbFreeLocks

    Bem falar é fácil, vamos tentar provar tudo o que foi dito nesta seção. Vejamos um
    exemplo que utiliza os métodos aqui expostos e como o jet se comporta :
    -Aguardem exemplo... - Bloqueio de registros.

    Conteúdo

AGUARDEM CONTINUAÇÃO...

Retorna