Caminho físico x caminho virtual para BD Access

Um erro relativamente comum por parte de desenvolvedores ainda sem muita experiênia, e que os leva frequentemente a achar que existe algum problema no servidor, é o caminho de Bancos de Dados Access.

Comumente o usuário tem, em sua máquina local, um banco no caminho…

c:\inetpub\wwwroot\bd\meubanco.mdb

Funciona em sua máquina local, e quando a página que usa o banco é enviada para o servidor… “A página não pode ser exibida”. A conclusão precipitada, muitas vezes, é que “há um problema no servidor, porque a página está correta, e roda em minha máquina“.

O desenvolvedor deve usar sempre um Caminho Virtual para não ter problemas se houver alguma mudança na configuração do servidor, ou se mudar de provedor e ainda para manter a compatibilidade, usando o mesmo código em seu servidor local e no servidor do produção (o do provedor). Se criou uma pasta “/data” e para lá enviou “meubanco.mdb” deverá usar, como caminho…

Server.MapPath("\data\meubanco.mdb")

A função Server.MapPath retorna (ou ‘traduz’) o caminho físico correspondente ao caminho virtual informado. No servidor local, como exempleficado, um…

Response.Write Server.Mappath("\") vai gerar…

c:\inetpub\wwwroot\

… e provavelmente será diferente no servidor do provedor. Assim é mantida a compatibilidade, não sendo necessário alterar o código para fazer o ‘upload’.

Comentario (1)

Noções básicas de modelagem de dados

O primeiro banco de dados com o qual os desenvolvedores ASP tomam contato (e estamos considerando os iniciantes!) costuma ser o Microsoft Access. Ainda que o MS Access não seja exatamente um SGBD (Sistema Gerenciador de Banco de Dados), serve para exercitar conhecimentos elementares (e até alguns avançados) quanto à administração de dados. Um problema comum é que, dada a sua simplicidade, comumente o desenvolvedor não planeja seu banco de dados, não toma cuidado com a modelagem de dados. Um bom modelo de dados é fundamental para o funcionamento de uma aplicação cuja função seja o gerenciamento de dados (vide administração de dados), quer para simples exibição dos mesmos, quer para auxílio à decisão. Uma folha de horas trabalhadas é um exemplo de dados armazenados para exibição. Uma decisão (desconto ou pagamento de horas extras) pode estar envolvida aí, mas não chega a ser como a análise de compras de insumos, de maneira que a aplicação possa sugerir o ponto de compra de produtos de um mesmo fornecedor uma forma tal que não haja falta no estoque e que possa ser feita uma compra maior, se isso gerar um desconto. A mesma análise pode ser feita para, por uma questão de fluxo de caixa, não ser necessário comprar vários insumos ao mesmo tempo. Aí o auxílio à decisão está bem melhor caracterizado!

Alguns cuidados elementares que um desenvolvedor inexperiente costuma deixar de tomar são:

  • Deixar todos os campos texto com tamanho 50, que é o padrão oferecido pelo Access;
  • Definir como textos campos que conterão datas;
  • Utilizar constantes do tipo ‘cadeia de caracteres’ para campos que terão conteúdo repetido em muitos registros;

Vamos analisar, sumariamente, as conseqüências de cada um dos erros citados acima. São exemplo, mas não os únicos!

1. Em campo matrícula, que usará no máximo 6 caracteres, por exemplo, cada registro ocupará outros 44 bytes desnecessariamente. E como provavelmente esse seja um campo chave, o desperdício aumenta, acarretamento, ainda, problemas de performance;

2. É comum, embora completamente desaconselhável, usar campos texto para armazenar datas. Os mais ‘espertos’ armazenam no formato ‘aaaammdd’, o que ao menos permite uma exibição ordenada, crescente ou decrescente, no formato dd/mm/aaaa. O problema, nesse caso, é não podermos (ao menos diretamente), obter o dia da semana referente à data e, principalmente, não poder executar cálculos com as datas. Calcular intervalos entre 2 datas nesse formato, ou avançar ‘n‘ meses a partir de uma data será algo descartado. Tudo bem, eu e muitos outros da ‘velha guarda’ já fizemos esse tipo de rotina em Turbo Pascal, criando bibliotecas de funções com ‘zilhões’ de linhas. Era o tempo em que o grande prezer do desenvolvedor não era exatamente o funcionamento do sistema, mas ter criado as ferramentas que permitiam ao computador, uma máquina burra, fazer esse tipo de processamento. Era a época, passado remoto, em que criar uma rotina de entrada de dados em formatos que hoje vemos nos caixas eletrônicos ou nos ‘formulários’ exigia profundos conhecimentos de lógica de programação, e freqüentemente o domínio de uma matemática relativamente avançada.

3. Esse erro é, talvez, o que mais caracteriza uma modelagem não muito bem feita. Suponhamos que os usuários tenham ‘poderes’ diferentes na aplicação, com critérios baseados em uma posição dentro da organização, e que cada usuário possa ser ‘classificado’ como ‘administrador’, ’supervisor’ e ‘operador’. É terrivelmente comum ver um banco em que, um campo de 50 caracteres contenha a descrição dessa posição. Em alguns casos o desenvolvedor ainda diminui o tamanho do campo para 15 caracteres, crente que está abafando! E vemos na tabela alguns registros com o tal campo preenchido com ‘administrador’, umas dezenas preenchidos com ’supervisor’ e algumas centenas (ou mesmo milhares!) com ‘operador’. E o que acontece se, por questões administrativas, for decidido transformar ‘operador’ em ‘usuário’. Centenas (ou milhares!) de registros precisarão ser atualizados. A saída? Um campo caracter de uma posição (char(1)), se não forem mais do que 10 diferentes ‘status‘, ou um campo ‘número tipo byte’. Em nosso exemplo, poderia ser char(1), com conteúdos ‘1′,’2′ ou ‘3′. Em uma outra tabela teríamos essa nomenclatura: 1 = ‘administrador’, 2 = ’supervisor’ e 3 = ‘operador’. Muito mais objetivo, não? Pior ainda seria criar uma tabela com a lista de direitos, por exempo, em que os registros contenham ‘administrador’, ’supervisor’, ‘operador’. Nesse caso o relacinamento seria pelo campo ’status’ (por exemplo). Nunca faça relacionamentos utilizando campos caracter.

Em uma ficha cadastral, por exemplo, na qual um dos campos seja ‘país’, a criação de uma tabela com a lista de países, cada um com um número, evita que um determinado campo seja preenchido ‘trocentas vezes’ com BRASIL. O campo conteria o número correspondente a Brasil na tabela de países. Nesse caso, por razões que não vem ao caso aqui, é até interessante usar a tabela internacional, onde o Brasil tem o número 55. E é muito mais fácil pesquisar pelo código 55 do que por Brasil, principalmente se considerarmos que não poucos escreverão BraZil!

Comentarios

Porque a pasta ‘/data’ (ou ‘/db’) está fora de ‘/wwwroot’?

O problema é que se alguém faz um acesso ao caminho do seu banco (por exemplo, http://www.seudominio.com.br/data/seubanco.mdb) o mesmo poderá ser baixado. Para evitar isso você deve colocar o banco na pasta /data fora do site (no mesmo nível da /wwwroot).

Uma vez que o banco esteja lá, você deve ir, no painel, à ODBC DSNs. Crie uma DSN, escolhendo um nome (por exemplo, meubanco, mas pode ser qualquer um) e criando uma string de conexão. Sua string de conexão passará a ser, então:

< %
strConn = “DSN=meubanco”
%>

Fica simples, independente do caminho, e o banco fica protegido contra downloads.

Comentarios