VB X ACCESS
Boa tarde pessoal,
Estou escrevendo uma aplicacao para varios usuarios que vao acessar sumultaneamente o bd.
Nao tenho pratica em desenvolver aplicacoes em access e nesta sera preciso.
Sempre quando desenvolvo utilizo sql server.
Gostaria de saber boas praticas para utilzar um mdb pois ele é mais sucetiveis a erro do que um sql server. (creio eu)
Ah. Esta aplicacao vao ter muitas informacoes. Estava pesando em utilizar o controle tabStrip mas ele é meio chato de usar. Alguem sugere alum controle ou tecnica para dispor muita informacao na tela?
Muito obrigado
Alexandre.
Estou escrevendo uma aplicacao para varios usuarios que vao acessar sumultaneamente o bd.
Nao tenho pratica em desenvolver aplicacoes em access e nesta sera preciso.
Sempre quando desenvolvo utilizo sql server.
Gostaria de saber boas praticas para utilzar um mdb pois ele é mais sucetiveis a erro do que um sql server. (creio eu)
Ah. Esta aplicacao vao ter muitas informacoes. Estava pesando em utilizar o controle tabStrip mas ele é meio chato de usar. Alguem sugere alum controle ou tecnica para dispor muita informacao na tela?
Muito obrigado
Alexandre.
Por experiência PROPRIA:
1 - Se a aplicação for rodar em rede, nunca use controles vinculados!!!
O Acesso declarado é sempre mais viável...
2 - Nas instruções SQL ese e abuse de begintrans e commitTrans!! Mas cuidado com o desempenho
3 - Veja o artigo que o FLÃ ÂVIO postou para EVITAR que o Access se comprometa... (http://www.vbmania.com.br/vbmdetail.php?varID=2768)
5 - Tente evitar ao máximo consulta com * (selecionar todos os campos)
Selecione somente o que irá precisar
6 - Assim como os campos, selecione somente os REGISTROS que irá precisar
Ex: Num login, a maioria carregar com o form todos os nomes e senha para depois validar...
O Correto seria... a pessoa digitar o nome, e neste momento a aplicação procura somente os dados referentes ao login...
7 - Dependendo do tipo de Banco... use o BLOQUEIO OTIMISTA...
8 - DE MUITA ATENÇÃO NA MODELAGEM DE DADOS
(http://www.vbmania.com.br/vbmforum.php?varMethod=Abrir&varID=57540)
Tem outras e claro.. mas acho que é só.. por em quanto...
Espero ter ajudado...
1 - Se a aplicação for rodar em rede, nunca use controles vinculados!!!
O Acesso declarado é sempre mais viável...
2 - Nas instruções SQL ese e abuse de begintrans e commitTrans!! Mas cuidado com o desempenho
3 - Veja o artigo que o FLÃ ÂVIO postou para EVITAR que o Access se comprometa... (http://www.vbmania.com.br/vbmdetail.php?varID=2768)
5 - Tente evitar ao máximo consulta com * (selecionar todos os campos)
Selecione somente o que irá precisar
6 - Assim como os campos, selecione somente os REGISTROS que irá precisar
Ex: Num login, a maioria carregar com o form todos os nomes e senha para depois validar...
O Correto seria... a pessoa digitar o nome, e neste momento a aplicação procura somente os dados referentes ao login...
7 - Dependendo do tipo de Banco... use o BLOQUEIO OTIMISTA...
8 - DE MUITA ATENÇÃO NA MODELAGEM DE DADOS
(http://www.vbmania.com.br/vbmforum.php?varMethod=Abrir&varID=57540)
Tem outras e claro.. mas acho que é só.. por em quanto...
Espero ter ajudado...
oque seria um BLOQUEIO OTIMISTA?
E sobre a segunta parte da minha pergunta??
Sei que voce faz telas muito legais. Pode me dar umas sugestoes?
E sobre a segunta parte da minha pergunta??
Sei que voce faz telas muito legais. Pode me dar umas sugestoes?
Situação
-------------------
tabela.edit
.....
tabela.update
Pessimista= Ele começa a bloquear a partir do edit e só libera quando for dado o update.
Otimista= Ele durante a execução do comando "update"
-------------------
tabela.edit
.....
tabela.update
Pessimista= Ele começa a bloquear a partir do edit e só libera quando for dado o update.
Otimista= Ele durante a execução do comando "update"
me de um exemplo de otimista... nao entendi muito bem...
Não esqueça de fazer a referência a "microsoft activex data objects 2.X library
ADO com otimista
------------------------
Dim rs As New ADODB.Recordset
Dim conexao As New ADODB.Connection
conexao.Open "driver={sql server};provider=sqloledb.1;uid=sa;pwd=senha;server=(local);database=furnas"
rs.Open "select * from tb_forma_pgto where id_forma_pgto=12", conexao, adOpenDynamic, adLockOptimistic
rs.Fields("nm_forma_pgto") = "teste2"
rs.Update
Pessimista
---------------
Dim rs As New ADODB.Recordset
Dim conexao As New ADODB.Connection
conexao.Open "driver={sql server};provider=sqloledb.1;uid=sa;pwd=senha;server=(local);database=furnas"
rs.Open "select * from tb_forma_pgto where id_forma_pgto=12", conexao, adOpenDynamic, adLockPessimistic
rs.Fields("nm_forma_pgto") = "teste2"
rs.Update
ADO com otimista
------------------------
Dim rs As New ADODB.Recordset
Dim conexao As New ADODB.Connection
conexao.Open "driver={sql server};provider=sqloledb.1;uid=sa;pwd=senha;server=(local);database=furnas"
rs.Open "select * from tb_forma_pgto where id_forma_pgto=12", conexao, adOpenDynamic, adLockOptimistic
rs.Fields("nm_forma_pgto") = "teste2"
rs.Update
Pessimista
---------------
Dim rs As New ADODB.Recordset
Dim conexao As New ADODB.Connection
conexao.Open "driver={sql server};provider=sqloledb.1;uid=sa;pwd=senha;server=(local);database=furnas"
rs.Open "select * from tb_forma_pgto where id_forma_pgto=12", conexao, adOpenDynamic, adLockPessimistic
rs.Fields("nm_forma_pgto") = "teste2"
rs.Update
A Idéia melhor é não BLOQUEAR REGISTROS...
Num ambiente multi-usuários o programador tem sempre que se preocupar com o problema do uso simultà ¢neo das mesmas informações por vários usuários. [txt-color=#ff0000]O que muitas vezes se faz é recorrer ao bloqueio de registros[/txt-color], [txt-color=#0000ff]que pode ser feito só no momento da alteração do registro ou tão logo o usuário o acesse para iniciar uma atualização[/txt-color]. Se partirmos para a segunda forma de bloqueio, vamos segurar um registro bloqueado por quanto tempo? E se o usuário que o está bloqueando sair para almoçar ou tomar um café? Seja qual for a forma de bloqueio nenhuma delas é boa. [txt-color=#ff0000]O bloqueio otimista, que só se dá no momento da atualização, não nos impede de acessar um registro, exibir suas informações na tela e, baseado nestas informações, realizar uma alteração que pode estar em total discordà ¢ncia com o estado atual do registro no momento em que o atualizamos. Enquanto exibimos os dados, um outro usuário pode acessar o mesmo registro e fazer uma alteração que cria uma condição completamente nova na base de dados.[/txt-color] Além de desconhecermos esta alteração (o que poderia nos fazer mudar de idéia a respeito da nossa atualização), também poderemos estar enviando dados antigos para a base de dados e desfazendo o que o outro usuário acabou de fazer.
[txt-color=#0000ff]Já o BLOQUEIO Pessimista BLOQUEIA os REGISTROS a partir do EDIT.[/txt-color]
O que fazer.... então... porque como já falei a ideia central é BLOQUEAR REGISTROS...
Nesta situação estamos diante do que se chama de uma colisão de dados. Como então lidar com o problema da concorrência pelas mesmas informações num ambiente multi-usuários e tratar as colisões de dados?
Há duas soluções que se pode usar. Uma é usar o conceito de "[txt-color=#ff0000]versão de registro[/txt-color]". Uma idéia bem simples e que dá maior liberdade e segurança no acesso à  s informações. A idéia é ter um identificador de versão para cada registro em cada tabela que será atualizada por múltiplos usuários. A versão pode ser implementada criando-se um campo numérico inteiro no layout de registro e com valor padrão 0. Toda vez que um registro é acessado para ser modificado, trazemos com seus dados também o campo que contém a identificação de versão do registro. Após reunirmos os dados para fazer a atualização, criamos uma instrução "UPDATE" da linguagem SQL onde condicionamos na cláusula WHERE que o registro somente será atualizado se o seu identificador de versão atual for igual à  quele que obtivemos no momento que acessamos seus dados. Se esta condição estiver satisfeita, atualizaremos o registro acrescentando 1 ao valor atual do identificador de versão do registro. Exemplo:
"UPDATE Veiculos SET PLACA = 'AAA1234', CHASSI = '1234567890WERTYU', IdentificadorDeVersao = IdentificadorDeVersao + 1 WHERE CodVeiculo = 1000 AND IdentificadorDeVersao = " & lngUltimoIdentificadorDeVersaoObtido
Desta forma, se um outro usuário estiver visualizando o registro e quiser enviar uma atualização, seu identificador de versão não mais será igual à  quele que ele recebeu no momento que leu o registro anteriormente. E qualquer tentativa de atualizar o registro não se cumprirá, porque a condição de estar trabalhando com a versão mais atual do registro não será satisfeita na sua instrução "UPDATE".
Neste caso então, o programa deve verificar o número de registros afetados pela operação (neste caso será 0) e buscar na base de dados os valores atuais para os campos do registro. Comparará campo a campo os seus dados com os atuais e mostrará uma mensagem para o usuário informando o que mudou e perguntando se deve continuar. Caso o usuário concorde em atualizar o registro, uma nova tentativa de envio dos dados será feita, mas só que agora informando o identificador de versão mais atual para não haver novamente o conflito. Caso um outro usuário tenha feito uma nova alteração neste intervalo de tempo, o identificador de versão terá sido modificado e o conflito se repetirá. O mesmo procedimento será seguido até que as versões de registros confiram ou o usuário cancele a atualização.
O inconveniente sério da abordagem acima é que o seu programa pode não ser o único a acessar a mesma base de dados. E como garantir então que os demais programas seguirão a mesma técnica nas atualizações de registros? Não há como garantir isto. Para simplificar as coisas ainda mais e evitar o inconveniente acima, podemos fazer o mesmo que o ADO faz quando chamamos o método UpdateBatch de um recordset. Quando se chama o método UpdateBatch, o ADO cria uma consulta de ação para cada registro que precisa ser incluÃdo, atualizado ou excluÃdo. Em uma atualização, a consulta de ação é criada usando o critério da cláusula WHERE para comparar os valores de todos os campos do registro que será atualizado com os valores que estes campos tinham no momento que foram lidos. Se houver alguma diferença, é porque outro usuário já atualizou o registro ou o excluiu, e o número de registros afetados pela operação será zero. Verificando o número de registros afetados pela consulta e a não ocorrência de erros, o programa atualizador tem como saber se houve uma colisão de dados. Nestes casos, é feita uma consulta para recuperar o estado atual do registro e retorná-lo para o usuário com as devidas comparações. Isto nos livra de ter que usar um campo em cada tabela para indicar a versão de registros e também nos tira do risco de uma outra aplicação produzir inconsistências no nosso modo de trabalhar. O inconveniente aqui é o de ter de criar consultas tão longas quantos forem os campos da tabela a ser atualizada. Você pode perguntar: E por que não usar logo o método UpdateBatch do recordset ADO? Bem, se você estiver trabalhando em três camadas, irá descobrir o inconveniente de não conseguir retornar o valor da propriedade UnderlyingValue dos campos de um recordset desconectado. Esta propriedade é usada pelo método Resync que você chamaria para tratar colisões de dados após um UpdateBatch. O método Resync, adequadamente chamado, colocaria nesta propriedade os valores atuais dos campos do registro conflitante para que você os comparasse com os valores da propriedade OriginalValue de cada campo. Como os valores de UnderlyingValue não são retornados para o cliente, você teria o trabalho de montar um esquema de retorno destes dados feito à  parte. Além disto, o automatismo de UpdateBatch pode dificultar o seu controle sobre a operação, principalmente se você estiver trabalhando com Access. Você pode, por exemplo, querer gravar históricos para as operações que são feitas em cada registro. Vale lembrar também que, para trabalhar com os métodos UpdateBatch e Resync, você precisará ter no recordset os campos chave primária de qualquer tabela fornecedora de campos para a consulta geradora do recordset. O ADO precisa destas informações para montar suas consultas internamente.
Sacou??
Num ambiente multi-usuários o programador tem sempre que se preocupar com o problema do uso simultà ¢neo das mesmas informações por vários usuários. [txt-color=#ff0000]O que muitas vezes se faz é recorrer ao bloqueio de registros[/txt-color], [txt-color=#0000ff]que pode ser feito só no momento da alteração do registro ou tão logo o usuário o acesse para iniciar uma atualização[/txt-color]. Se partirmos para a segunda forma de bloqueio, vamos segurar um registro bloqueado por quanto tempo? E se o usuário que o está bloqueando sair para almoçar ou tomar um café? Seja qual for a forma de bloqueio nenhuma delas é boa. [txt-color=#ff0000]O bloqueio otimista, que só se dá no momento da atualização, não nos impede de acessar um registro, exibir suas informações na tela e, baseado nestas informações, realizar uma alteração que pode estar em total discordà ¢ncia com o estado atual do registro no momento em que o atualizamos. Enquanto exibimos os dados, um outro usuário pode acessar o mesmo registro e fazer uma alteração que cria uma condição completamente nova na base de dados.[/txt-color] Além de desconhecermos esta alteração (o que poderia nos fazer mudar de idéia a respeito da nossa atualização), também poderemos estar enviando dados antigos para a base de dados e desfazendo o que o outro usuário acabou de fazer.
[txt-color=#0000ff]Já o BLOQUEIO Pessimista BLOQUEIA os REGISTROS a partir do EDIT.[/txt-color]
O que fazer.... então... porque como já falei a ideia central é BLOQUEAR REGISTROS...
Nesta situação estamos diante do que se chama de uma colisão de dados. Como então lidar com o problema da concorrência pelas mesmas informações num ambiente multi-usuários e tratar as colisões de dados?
Há duas soluções que se pode usar. Uma é usar o conceito de "[txt-color=#ff0000]versão de registro[/txt-color]". Uma idéia bem simples e que dá maior liberdade e segurança no acesso à  s informações. A idéia é ter um identificador de versão para cada registro em cada tabela que será atualizada por múltiplos usuários. A versão pode ser implementada criando-se um campo numérico inteiro no layout de registro e com valor padrão 0. Toda vez que um registro é acessado para ser modificado, trazemos com seus dados também o campo que contém a identificação de versão do registro. Após reunirmos os dados para fazer a atualização, criamos uma instrução "UPDATE" da linguagem SQL onde condicionamos na cláusula WHERE que o registro somente será atualizado se o seu identificador de versão atual for igual à  quele que obtivemos no momento que acessamos seus dados. Se esta condição estiver satisfeita, atualizaremos o registro acrescentando 1 ao valor atual do identificador de versão do registro. Exemplo:
"UPDATE Veiculos SET PLACA = 'AAA1234', CHASSI = '1234567890WERTYU', IdentificadorDeVersao = IdentificadorDeVersao + 1 WHERE CodVeiculo = 1000 AND IdentificadorDeVersao = " & lngUltimoIdentificadorDeVersaoObtido
Desta forma, se um outro usuário estiver visualizando o registro e quiser enviar uma atualização, seu identificador de versão não mais será igual à  quele que ele recebeu no momento que leu o registro anteriormente. E qualquer tentativa de atualizar o registro não se cumprirá, porque a condição de estar trabalhando com a versão mais atual do registro não será satisfeita na sua instrução "UPDATE".
Neste caso então, o programa deve verificar o número de registros afetados pela operação (neste caso será 0) e buscar na base de dados os valores atuais para os campos do registro. Comparará campo a campo os seus dados com os atuais e mostrará uma mensagem para o usuário informando o que mudou e perguntando se deve continuar. Caso o usuário concorde em atualizar o registro, uma nova tentativa de envio dos dados será feita, mas só que agora informando o identificador de versão mais atual para não haver novamente o conflito. Caso um outro usuário tenha feito uma nova alteração neste intervalo de tempo, o identificador de versão terá sido modificado e o conflito se repetirá. O mesmo procedimento será seguido até que as versões de registros confiram ou o usuário cancele a atualização.
O inconveniente sério da abordagem acima é que o seu programa pode não ser o único a acessar a mesma base de dados. E como garantir então que os demais programas seguirão a mesma técnica nas atualizações de registros? Não há como garantir isto. Para simplificar as coisas ainda mais e evitar o inconveniente acima, podemos fazer o mesmo que o ADO faz quando chamamos o método UpdateBatch de um recordset. Quando se chama o método UpdateBatch, o ADO cria uma consulta de ação para cada registro que precisa ser incluÃdo, atualizado ou excluÃdo. Em uma atualização, a consulta de ação é criada usando o critério da cláusula WHERE para comparar os valores de todos os campos do registro que será atualizado com os valores que estes campos tinham no momento que foram lidos. Se houver alguma diferença, é porque outro usuário já atualizou o registro ou o excluiu, e o número de registros afetados pela operação será zero. Verificando o número de registros afetados pela consulta e a não ocorrência de erros, o programa atualizador tem como saber se houve uma colisão de dados. Nestes casos, é feita uma consulta para recuperar o estado atual do registro e retorná-lo para o usuário com as devidas comparações. Isto nos livra de ter que usar um campo em cada tabela para indicar a versão de registros e também nos tira do risco de uma outra aplicação produzir inconsistências no nosso modo de trabalhar. O inconveniente aqui é o de ter de criar consultas tão longas quantos forem os campos da tabela a ser atualizada. Você pode perguntar: E por que não usar logo o método UpdateBatch do recordset ADO? Bem, se você estiver trabalhando em três camadas, irá descobrir o inconveniente de não conseguir retornar o valor da propriedade UnderlyingValue dos campos de um recordset desconectado. Esta propriedade é usada pelo método Resync que você chamaria para tratar colisões de dados após um UpdateBatch. O método Resync, adequadamente chamado, colocaria nesta propriedade os valores atuais dos campos do registro conflitante para que você os comparasse com os valores da propriedade OriginalValue de cada campo. Como os valores de UnderlyingValue não são retornados para o cliente, você teria o trabalho de montar um esquema de retorno destes dados feito à  parte. Além disto, o automatismo de UpdateBatch pode dificultar o seu controle sobre a operação, principalmente se você estiver trabalhando com Access. Você pode, por exemplo, querer gravar históricos para as operações que são feitas em cada registro. Vale lembrar também que, para trabalhar com os métodos UpdateBatch e Resync, você precisará ter no recordset os campos chave primária de qualquer tabela fornecedora de campos para a consulta geradora do recordset. O ADO precisa destas informações para montar suas consultas internamente.
Sacou??
Afe... Saquei.
Nao entendi direito o lance de update bach....
E as sugestao das telas?????? Uso Tabstrip, varios forms???
Nao entendi direito o lance de update bach....
E as sugestao das telas?????? Uso Tabstrip, varios forms???
Cara sobre as telas, depende da máquina onde vc vai desenvolver e da máquina aonde o cliente vai rodar o programa, a LÓ“GICA é sempre OTIMIZAR recursos... ou seja, telas BONITAS porêm leves, simples e diretas...
Quanto aos TABS... só uso quando os campos dos dados não cabem em um FORM... fora isso... vou criando vários FORMS mesmo!!
Quanto aos TABS... só uso quando os campos dos dados não cabem em um FORM... fora isso... vou criando vários FORMS mesmo!!
http://www.vbmania.com.br/vbmforum.php?varMethod=Abrir&varID=70435&varSubPagina=1&varFiltro=Nulo
Aqui há vários exemplos de telas!!!
Aqui há vários exemplos de telas!!!
Tópico encerrado , respostas não são mais permitidas