Tutorial de ADO

Aqui você poderá oferecer suas Contribuições, Dicas e Tutoriais (Texto ou Vídeo) que sejam de interesse de todos.

Moderador: Moderadores

Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Tutorial de ADO

Mensagem por JoséQuintas »

Na época que comecei, fez falta um tutorial desse tipo.

Por enquanto é a parte teórica.
Se preocupe em entender do que se trata, e deixe a parte de como usar pra depois.
Usar é mais simples do que entender.

Nos tempos do Clipper, o único tipo de biblioteca que conhecemos foi do tipo LIB, que linqueditamos ao programa.

O Blinker acrescentou ao Clipper um recurso muito conhecido do Windows, que foi poder gerar/usar DLLs.
A DLL é como se fosse uma parte do EXE, mas diferente das antigas overlays, com vida própria.
Era possível compilar o EXE ou a DLL de forma separada, podendo trocar qualquer uma das duas partes depois.
Vantagens: mais prático compilar partes menores, e partes poderiam ser compartilhadas por vários programas.
Como Clipper é 16 bits, de qualquer forma não pode aproveitar as muitas DLLs existentes no Windows.

O Windows é cheio de DLLs, todas prontas pra uso, com funções diversas.
As DLLs podem ser divididas em 2 tipos:

- As que são instaladas no Windows, e ficam prontas pra uso, como a do Excel ou Internet Explorer.
- As que NÃO são instaladas no WIndows, como a BLAT.DLL

Como a DLL pode ser de qualquer linguagem (até em Clipper), não significa que qualquer programa pode acessar qualquer DLL.
Além de outras coisas, algumas linguagens tem tipos de variáveis que outras não tem.

O ADO é uma bilbioteca que vém instalada no Windows, pronta pra uso.
Foi criado para que o acesso a qualquer banco de dados seja feito sempre da mesma forma, sem precisar conhecer os detalhes de cada banco de dados.
Há várias formas de usar o ADO, e há muitos recursos, mas não é o objetivo deste tutorial mostrar tudo.
Qualquer coisa, há vários manuais na internet, pra quem quiser se aprofundar ainda mais.

É bom entender o que é objeto, propriedades, métodos e coleções, pra fazer uso dos manuais que se encontram na internet.

No mundo Clipper conhecemos variável, função.
Variável podendo conter string, número, data, etc.
Função, que faz parte do programa.

Inventaram uma variável que pode conter tudo ao mesmo tempo: variável e função.
Deram o nome pra isso de objeto.
É diferente de biblioteca, porque podemos alterar qualquer conteúdo desse objeto - mesmo o que seria uma função.
É como criar um programa, com rotinas, e poder trocar as rotinas, isso durante a execução, sem compilar/linqueditar.
E as variáveis e funções do objeto recebem o nome de propriedades e métodos.
É como se fosse a mesma coisa com nome trocado, mas por causa do funcionamento diferente, recebeu outro nome.
Também tem a coleção, que poderia ser comparado a um array.

Só pra comparação, dbStruct() retorna uma coleção, onde cada item da coleção se refere a um campo do arquivo.

Então, objeto é um pacote que pode conter suas variáveis e funções, e até mesmo outros objetos.
Geralmente usamos uma variável pra armazenar esse "pacote".

No Harbour podemos criar objetos, são as classes. E podemos usar objetos prontos.

Um pacote dipsonível no Windows é o ADO.
Dentro do ADO temos alguns objetos:

Connection - Contém as funções pra "conversar" com a base de dados.
Recordset - Poderíamos comparar com um DBF, mas tem formato próprio.

Pra não depender de nada, esses objetos contém funções que podem ser usadas pra acesso.
Comparando Clipper ao ADO:
Em Clipper, dbStruct() retorna uma coleção contendo cada campo do arquivo com nome, tipo, tamanho, decimais.
Em ADO, Fields(), retorna uma coleção contendo esse tipo de informação, além de funções relacionadas.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Tutorial de ADO

Mensagem por JoséQuintas »

Vamos ao que interessa: como usar.

Pra conversar com o banco de dados, precisa da conexão.
É a única ligação entre o programa e o banco de dados, como se fosse uma linha telefônica, ou uma janela do Skype.
Para um programa inteiro, pode ser usada uma única conexão com o banco de dados.
Nela indicamos localização (que pode ser IP ou diretório), usuário, senha, tipo de banco de dados, etc.
É o principal objeto, porque vai dizer exatamente como encontrar a base de dados, e como deverá ser usada.

Código: Selecionar todos

oConexao := win_OleCreateObject( "ADODB.Connection" )
Como é objeto, contém suas "variáveis" e suas "rotinas"
A primeira coisa é configurar essas "variáveis" de acordo com a base de dados.

Aqui uso assim para o MySql:

Código: Selecionar todos

   cnConnection:= win_OleCreateObject( "ADODB.Connection" )
   cnConnection:ConnectionString := "Driver={MySQL ODBC 3.51 Driver};Server=" + cServer + ";" + "Port=" + Ltrim( Str( nPort ) ) + ;
      ";Stmt=;Database=" + cDatabase + ";User ID=" + cUser + ";Password=" + cPassword + ";Collation=latin1;" + ;
      "UseCompression;" // Option=131072;
   cnConnection:CursorLocation    := adUseClient   // local recordset
   cnConnection:CommandTimeOut    := 120 // seconds
   cnConnection:ConnectionTimeOut := 120 // seconds
O que são essas "variáveis" (propriedades):

:ConnectionString é a string de conexão, é o texto que indica tudo sobre a base de dados. Tanto faz se é MySQL, DBF por ADS, Postgress. Cada banco de dados vai ter sua própria string. No caso do ADS, Excel e Access, por exemplo, vai conter também o nome do diretório. No caso do MySQL contém IP do servidor, porta de comunicação, nome do banco de dados, usuário, senha, e até configurações extras.

:CursorLocation indica se o recordset (arquivo temporário) vai ser criado no servidor ou no terminal

:CommandTimeOut indica o tempo limite pra esperar uma resposta

:ConnectionTimeOut indica o tempo limite pra esperar conectar
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Tutorial de ADO

Mensagem por JoséQuintas »

Métodos (funções) da conexão:

:Open() - pra ativar/abrir

:Close() - pra desativar/fechar

:Execute() - pra executar um comando

Não parece, mas só esses três e está tudo resolvido.

Pode abrir no início do aplicativo, e fechar antes de encerrar o aplicativo.

No restante, é Execute(). Qualquer coisa que vá fazer com o banco de dados, é Execute().

Compare o Execute() com uma janela do Skype. Vai mandar uma mensagem ao banco de dados, e ele vai te responder.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Tutorial de ADO

Mensagem por JoséQuintas »

Esqueci de mencionar no início:
Apesar de ser pra ADO, pode servir pra entender o básico da comunicação cliente/servidor.
Também pra entender o básico de objetos, propriedades, métodos e coleção - vai ter muito nos manuais da internet
Também pra entender o básico de DLLs, algumas vezes chamadas de componentes, activex, etc. devido a características de cada um
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Tutorial de ADO

Mensagem por JoséQuintas »

No meu caso, pra deixar um fonte mais limpo, criei uma função que faz a configuração para MySql.
Deixar separado, assim deixa o restante mais claro.

Código: Selecionar todos

FUNCTION MySqlConnection( cServer, nPort, cDatabase, cUser, cPassword )
   LOCAL cnConnection
   cnConnection:= win_OleCreateObject( "ADODB.Connection" )
   cnConnection:ConnectionString := "Driver={MySQL ODBC 3.51 Driver};Server=" + cServer + ";" + "Port=" + Ltrim( Str( nPort ) ) + ;
      ";Stmt=;Database=" + cDatabase + ";User ID=" + cUser + ";Password=" + cPassword + ";Collation=latin1;" + ;
      "UseCompression;" // Option=131072;
   cnConnection:CursorLocation    := adUseClient   // local recordset
   cnConnection:CommandTimeOut    := 120 // seconds
   cnConnection:ConnectionTimeOut := 120 // seconds
   RETURN cnConnection
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Tutorial de ADO

Mensagem por JoséQuintas »

Agora o aplicativo:

Código: Selecionar todos

PROCEDURE Main
   oConexao := MySqlConnection( cIP, nPort, cDatabase, cUser, cPassword )
   oConexao:Open()
   ...
   oConexao:Close()
   RETURN
Isso é pra ficar claro a parte importante.
No uso, pode ter uma única conexão pro aplicativo inteiro.
No meu uso prático, esse foi o melhor jeito.
O Harbour não era assim no início, mas depois mudaram.

Por incrível que pareça, isto pode gerar problemas:

Código: Selecionar todos

FOR nCont = 1 TO 10000
   oConexao:Open()
   oConexao:Close()
NEXT
Não existe limite para conexões abertas no Windows.
Conexão fechada não existe, porque uma vez fechada ela some.
Mas existem "half-open connections" que são conexões em fase de abertura ou em fase de fechamento.
Esse limite é baixo, então precisa tomar cuidado pra não travar tudo.
Não sei se é coisa apenas do Windows, mas existe um tempo adicional antes de fechar de vez, o que a deixa em estado de "half-open".

Quem usa Emule, Torrent e afins, já deve ter visto algo sobre isso.
Passou do limite, vai ficando numa fila de espera, correndo o risco de travar tudo.

Por isso simplifiquei, e abro/fecho no início e final do aplicativo.
O detalhe é que pra ser conexão única, essa variável precisa estar disponível a todos os módulos, mesmo em multithread.
Cada um já deve ter uma solução pronta pra isso: PUBLIC, STATIC, função, etc.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Tutorial de ADO

Mensagem por JoséQuintas »

Até aqui sabemos abrir, fechar, falta o resto - o Execute()

Como eu disse antes, é como se fossem mensagens no Skype.
Essas mensagens são em comandos SQL, que no geral obedecem um padrão.
Como os bancos de dados são diferentes, pode existir alguma variação, dependendo do recurso a mais que quiser.

O Execute() vai enviar mensagem, e pode trazer uma resposta. Tudo depende de qual comando enviou.
A resposta pode ser justamente o recordset - o "arquivo temporário".

Agora exemplos simbólicos, já que algumas coisas dependem de detalhes específicos de cada base de dados.
Notem que a partir daqui, tem a ver com comandos SQL.

Criar uma tabela, o que seria equivalente a criar um DBF:

Código: Selecionar todos

oConexao:Execute( "CREATE TABLE minhatabela ( CODIGO NUMERIC(5), NOME CHAR(30), VALOR NUMERIC(12,2) )" )
Incluir um ou mais registros:

Código: Selecionar todos

oConexao:Execute( "INSERT INTO minhatabela ( CODIGO, NOME ) VALUES ( 5, 'TESTE', 10 )" )
Excluir:

Código: Selecionar todos

oConexao:Execute( "DELETE FROM minhatabela WHERE CODIGO=5" )
Alterar:

Código: Selecionar todos

oConexao:Execute( "ALTER TABLE minhatabela SET NOME='TESTE2'  WHERE CODIGO=5" )
Pesquisar:

Código: Selecionar todos

oTemporario := oConexao:Execute( "SELECT * FROM minhatabela" )
O pesquisar expande as possibilidades, porque não se limita a apenas aos campos existentes.
Poderia pesquisar a soma de todos os campos valor.
E como essa soma não tem nome definido, podemos chamá-la de soma, pra facilitar depois.

Código: Selecionar todos

oTemporario := oConexao:Execute( "SELECT SUM(VALOR) AS SOMA FROM minhatabela" )
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Tutorial de ADO

Mensagem por JoséQuintas »

Sobre os comandos SQL, a variedade é infinita, então vai ter que pesquisar tudo que é opção, conforme for precisando.
Principalmente para o comando SELECT.

O que precisa saber é:
Passou a ter um gerenciador de banco de dados, um "programa" que trabalha para o seu programa.
Seu programa manda a mensagem, e o servidor manda a resposta.
Seu programa pede: eu quero as vendas para clientes de São Paulo, totalizadas por cliente, mas me interessa apenas as vendas acima de 2.000, e quero em ordem alfabética de cliente.
E o servidor manda isso pronto para o programa.

Não compensa fazer isso igual DBF.
Imagine o programa pedindo a lista de todos os clientes, todas as vendas, para o próprio programa selecionar o que interessa, totalizar, indexar, etc.
Se pode vir pronto, é menos processamento no terminal, e menos informações pela rede.
Mesmo que precise de um comando grande pra enviar ao servidor, a resposta vai ser pequena, então vale a pena.

A título de curiosidade, seria um comando parecido com este, dependendo da configuração das bases de dados, poderia até ser menor.

Código: Selecionar todos

oConexao:Execute( "SELECT CODCLI, CLIENTES.NOME AS NOMECLI, SUM(VALOR) AS SOMA FROM " + ;
   "VENDAS INNER JOIN CLIENTES ON CODCLI = CLIENTES.CODCLI WHERE VALOR > 2000 GROUP BY CODCLI ORDER BY NOMECLI" )
Qual informação vai retornar, que será o conteúdo do recordset (como arquivo temporário)
CODCLI, CLIENTES.NOME AS NOMECLI, SUM(VALOR) AS SOMA

De onde ela vém:
VENDAS

Criando um relacionamento com a tabela de clientes pra pegar o nome (caso não tenha feito isso no servidor)
INNER JOIN CLIENTES ON CODCLI = CLIENTES.CODCLI

Um filtro:
WHERE VALOR > 2000

Como vai agrupar pra totalizar:
GROUP BY CODCLI

E a ordem final:
ORDER BY NOMECLI

Tem variações nesse comando, por exemplo o servidor identificar CODCLI nas duas tabelas e já relacionar, ou já ter sido definido no servidor, mas aí é cada um pesquisar o que há de disponível na base de dados que escolher.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Tutorial de ADO

Mensagem por JoséQuintas »

Agora vém a parte de usar o recordset, o "arquivo temporário" (que não é arquivo físico).

Como disse antes, o recordset não é apenas informação, tem também funções.
Então uma opção é usar diretamente, através das funções ADO.

Usar o último exemplo, onde o SELECT foi CODCLI, CLIENTES.NOME AS NOMECLI, SUM(VALOR) AS SOMA
Significa que os campos serão CODCLI, NOME e SOMA

Código: Selecionar todos

DO WHILE .NOT. oTemporario:Eof()
   ? oTemporario:Fields( "CODCLI" ):Value
   ? oTemporario:Fields( "NOME" ):Value
   ? oTemporario:Fields( "SOMA" ):Value
   oTemporario:MoveNext()
ENDDO
oTemporario:Close()
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Tutorial de ADO

Mensagem por JoséQuintas »

Outra opção, que estou usando para facilitar, é converter esse recordset em DBF.
Com ou sem ADO, as LIBs do Harbour costumam fazer isso, muitas vezes on-the-fly, conforme vai usando a informação retornada.

Já devem ter visto algo parecido com isto:

Código: Selecionar todos

USE ( "SELECT * FROM CLIENTES" ) ALIAS CLIENTES
Significa que o comando SQL está sendo executado e o retorno está sendo usado como se fosse um DBF.

No caso do ADO, algo equivalente poderia ser:

Código: Selecionar todos

cDBF := ConverteDbf( oConexao:Execute( "comandoSQL" ) )
USE ( cDbf ) ALIAS CLIENTES
E a função ConverteDbf() seria a única a ter o tratamento de ADO.
Ou até usar #define ou #command ou #translate pra deixar mais transparente ainda.
Mas infelizmente não sei usar essas coisas direito.

Basicamente é isso.

O que precisa?
Como qualquer outra opção, precisa do programa específico da base de dados, geralmente chamada ODBC.
Se for MySQL, o ODBC de MySQL.
Se for ADS pra DBF, o ODBC de ADS, e no Windows 64 bits precisa de uma configuração adicional que não descobri qual é

Até faz um pouco de sentido ser mais complicado pra DBF e outros tipos de odbc de uso local.
Imagine um programa acessar o ODBC de DBF, e salvar um DBF com o nome de C:\windows\system32\algumacoisa.
Tudo bem, muita coisa já melhorou na segurança do Windows pra evitar isso, mas... continua sendo considerado um risco à segurança...
Então a opção de DBF ainda existe, só precisa pesquisar.

Notas:
Na prática testei ADS no XP 32 bits e no W7 64 bits. No XP continua como sempre foi.
Na pesquisa disso na internet, há muita referência sobre acesso a bases de dados por uma "engine" Microsoft que deixou de vir pronta pra uso em 64 bits, o que leva a deduzir que o uso do ADS faz uso disso.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
ANDRIL
Usuário Nível 5
Usuário Nível 5
Mensagens: 1297
Registrado em: 06 Jul 2004 00:44
Contato:

Tutorial de ADO

Mensagem por ANDRIL »

José, ótima informação sobre o ADO. Parabéns!
Clipper 5.2e / Blinker 5.1 / Harbour 3.2 / GTwvg
frazato
Usuário Nível 3
Usuário Nível 3
Mensagens: 219
Registrado em: 08 Jul 2004 07:45

Tutorial de ADO

Mensagem por frazato »

Boa tarde! estou usando como base este código abaixo pra leitura e gravação em Msyql, cara tá show, o problema é só identificar o sucesso ou não da conecção, quanto tudo funciona blz, só que preciso saber quando deu algum problema ao conectar ou executar propriamente o comando, segue exemplo abaixo, grava em 2 bancos ao mesmo tempo.

Frazato

Código: Selecionar todos

#include "inkey.ch"

STATIC oConexaoFlex, oConexaoBridge
						   
PROCEDURE Main
   ConfiguraConexaoFlex()
   oConexaoFlex:Open()
   
   ConfiguraConexaoBridge()
   oConexaoBridge:Open()
   
   
   
   SET CENTURY ON
   SET DATE BRITISH
   SET EPOCH TO 2001
   SET DELETE ON
   SET MESSAGE TO 24 CENTER
   SetMode( 25, 80 )
   SET COLOR TO W/N,W/GR+,,,G+/N
   CLS
   
   Do while .t.
   ccodigo := space(5)
   nPreco  := 0
   @ 09,09 SAY 'Carga de Preco/Online GZ Flex / BrigeDB'
   @ 10,10 say 'Digite o codigo :' Get cCodigo pict '99999'
   @ 11,10 say 'Digite o Preco Venda :' Get nPreco pict '@EZ 999,999.99'
   read
   If LastKey()==27
      exit
   Endif
   
   VerProdutos(cCodigo,nPreco)
   
   Enddo
   oConexaoFlex:Close()
   oConexaoBridge:Close()
   
   Quit // Forca Saida
   
      *oTemporario := oConexao:Execute( "SELECT * FROM LOTES WHERE LOTE=" + Ltrim( Str( wLote ) ) )
      *IF oTemporario:RecordCount() != 0
      *   westado     = oTemporario:Fields( "ESTADO" ):Value
      *   wdt_entrada = datavol4( oTemporario:Fields( "DT_ENTRADA" ):Value )
      *   wdias       = oTemporario:Fields( "DIAS" ):Value
      *   wdt_saida   = datavol4( oTemporario:Fields( "DT_SAIDA" ):Value )
      *   wqtde       = oTemporario:Fields( "QTDE" ):Value
      *   wvlr_unit   = oTemporario:Fields( "VLR_UNIT" ):Value
      *   wvlr_total  = oTemporario:Fields( "VLR_TOTAL" ):Value
      *endif
      *oTemporario:Close()
      // exclusao
      *   if woquefazer = "INC"
      *      oConexao:Execute( "INSERT INTO LOTES ( LOTE ) VALUES ( " + Ltrim( Str( wLote ) ) )
      *   endif
      *   oConexao:Execute( [UPDATE LOTES SET ] + ;
      *      [ESTADO='] + wEstado + [', ] + ;
      *      [DT_ENTRADA='] + Dtos( wDt_Entrada ) + [', ] + ;
      *      [DIAS=] + Ltrim( Str( wDias ) ) + [, ] + ;
      *      [DT_SAIDA="] + Dtos( wDt_Saida ) + [", ] + ;
      *      [QTDE=] + Ltrim( Str( wQtde ) ) + [, ] + ;
      *      [VLR_UNIT=] + Ltrim( Str( wVlr_Unit ) ) + [, ] + ;
      *      [VLR_TOTAL=] + Ltrim( Str( wVlr_Total ) ) + [ ) ] + ;
      *      [WHERE LOTE=] + Ltrim( Str( wLote ) ) )
   oConexao:Close()
   RETURN


//--- Coneccao com o banco do Gz
//------------------------------------------------------------
STATIC FUNCTION ConfiguraConexaoFlex()
   Centra('Aguarde..... Conectando Bando Dados...GZFLEX...')
   oConexaoFlex := win_OleCreateObject( "ADODB.Connection" )
   oConexaoFlex:ConnectionString := "Driver={MySQL ODBC 3.51 Driver};Server=LocalHost;" + ;
      "Option=131072;Stmt=;Database=concentdb;User ID=root;Password=mestre;Collation=latin1;"
   oConexaoFlex:CursorLocation    := 3   // local recordset
   oConexaoFlex:CommandTimeOut    := 120 // seconds
   oConexaoFlex:ConnectionTimeOut := 120 // seconds
   centra('Aguarde..... Conectando Bando Dados...GZFLEX...')
   RETURN NIL
   
//--- --- --- --- --- --- --- --- --- --- --- --- --- --- ---    
STATIC FUNCTION ConfiguraConexaoBridge()
   Centra('Aguarde..... Conectando Bando Dados...GZFLEX...')
   oConexaoBridge := win_OleCreateObject( "ADODB.Connection" )
   oConexaoBridge:ConnectionString := "Driver={MySQL ODBC 3.51 Driver};Server=LocalHost;" + ;
      "Option=131072;Stmt=;Database=bridgedb;User ID=root;Password=mestre;Collation=latin1;"
   oConexaoBridge:CursorLocation    := 3   // local recordset
   oConexaoBridge:CommandTimeOut    := 120 // seconds
   oConexaoBridge:ConnectionTimeOut := 120 // seconds
   RETURN NIL
   
   //------------------------------------------------
   Static Function VerProdutos(cPesq,nPrecoVenda)
   LOCAL oTemporario, lOk := .T.
   Local ccodigo   := Alltrim(Str(val(cPesq)))
   Local cVenda    := Alltrim(Str(nPrecoVenda))
   centra('Gravando produto Bando de dados....'+cPesq)
   oTemporario := oConexaoFlex:Execute( [SELECT * FROM  ESTOQUE WHERE CDPROD=]+cCodigo )
   IF oTemporario:RecordCount() == 0
      Alert ( "Estado não encontrado" )
      lOK := .F.
   ELSE
      @ 12,12 SAY oTemporario:Fields( "descricao" ):Value COLOR "G+/N"
      @ 13,12 say oTemporario:Fields( "termvenda" ):Value COLOR "G+/N"
      
      oConexaoFlex:Execute( [UPDATE Estoque SET ] + ;
                        [termvenda=] + cVenda+[,]+ ;
                        [descpdv='Alterado via JAF']+ ;
                        [WHERE cdProd=] + cCodigo )
                        
                        //alert("INSERT INTO SOLICITACAO (TABELA) VALUES ('estoque')")
                        
       cVerCondicao  := 'p.cdprod = #@#'+Space(20-Len(cCodigo))+cCodigo+'#@#'
		 oConexaoBridge:Execute( [INSERT INTO solicitacao (TABELA,TIPO,IP,PORTA,USUARIO,CONDICAO) VALUES ('estoque','CP','192.168.27.106','1202','JAF ONLINE',']+cvercondicao+[')])
   ENDIF
   oTemporario:Close()
   RETURN lOk
   
   Function Centra(c)
   @ 24,00 say c
   Return nil

   
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Tutorial de ADO

Mensagem por JoséQuintas »

A checagem seria no Open()

Código: Selecionar todos

lOpen := .F.
BEGIN SEQUENCE
   Conexao:Open()
   lOpen := .T.
END SEQUENCE
IF .NOT. lOpen
   Mensagem( "Não conseguiu abrir" )
   QUIT
ENDIF
Ou se for usar isso muitas vezes:

Código: Selecionar todos

IF .NOT. OpenConn( Conexao )
   Mensagem( "Não conseguiu abrir" )
   QUIT
ENDIF

FUNCTION OpenConn( Conexao )
   LOCAL lOpen := .F.
   Mensagem( "Abrindo Conexão" )
   BEGIN SEQUENCE
      Conexao:Open()
      lOpen := .T.
   END SEQUENCE
   RETURN lOpen
De quebra, pode acrescentar pra mostrar possíveis mensagens de erro.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
frazato
Usuário Nível 3
Usuário Nível 3
Mensagens: 219
Registrado em: 08 Jul 2004 07:45

Tutorial de ADO

Mensagem por frazato »

Código: Selecionar todos

 ConfiguraConexaoFlex()
   BEGIN SEQUENCE WITH {| oErr | Break( oErr ) }
   	    oConexaoFlex:Open()
   RECOVER
          Alert('Erro ao conectar o Banco!')
          Return nil
   END SEQUENCE

   
   ConfiguraConexaoBridge()
   BEGIN SEQUENCE WITH {| oErr | Break( oErr ) }
   	    oConexaoBridge:Open()
   RECOVER
          Alert('Erro ao conectar o Banco!')
          Return nil
   END SEQUENCE
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Tutorial de ADO

Mensagem por JoséQuintas »

Mas com essas, como o programa vai saber se falhou?
Faltou retornar verdadeiro ou falso, pro programa decidir o que fazer.

Mais um detalhe:
Abre uma, deu erro, encerra.
Abre uma, ok, vai em frente.
Abre a outra, deu erro, fecha a primeira antes de encerrar.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Responder