Clipper On Line • Ver Tópico - Tutorial de ADO

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

 

Tutorial de ADO

Mensagempor JoséQuintas » 14 Jun 2015 22:11

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, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Tutorial de ADO

Mensagempor JoséQuintas » 14 Jun 2015 22:31

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.

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:
   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, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Tutorial de ADO

Mensagempor JoséQuintas » 14 Jun 2015 22:37

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, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Tutorial de ADO

Mensagempor JoséQuintas » 14 Jun 2015 22:44

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, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Tutorial de ADO

Mensagempor JoséQuintas » 14 Jun 2015 22:48

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.

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, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Tutorial de ADO

Mensagempor JoséQuintas » 14 Jun 2015 23:06

Agora o aplicativo:

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:

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, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Tutorial de ADO

Mensagempor JoséQuintas » 14 Jun 2015 23:31

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:

oConexao:Execute( "CREATE TABLE minhatabela ( CODIGO NUMERIC(5), NOME CHAR(30), VALOR NUMERIC(12,2) )" )


Incluir um ou mais registros:

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


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


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


Pesquisar:

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.

oTemporario := oConexao:Execute( "SELECT SUM(VALOR) AS SOMA FROM minhatabela" )
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Tutorial de ADO

Mensagempor JoséQuintas » 14 Jun 2015 23:52

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.

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, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Tutorial de ADO

Mensagempor JoséQuintas » 14 Jun 2015 23:58

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

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, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Tutorial de ADO

Mensagempor JoséQuintas » 15 Jun 2015 00:16

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:

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:

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, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Tutorial de ADO

Mensagempor ANDRIL » 15 Jun 2015 08:39

José, ótima informação sobre o ADO. Parabéns!
Clipper 5.2e / Blinker 5.1 / Harbour 3.2 / GTwvg
Avatar de usuário

ANDRIL
Usuário Nível 5

Usuário Nível 5
 
Mensagens: 1270
Data de registro: 06 Jul 2004 00:44
Curtiu: 12 vezes
Mens.Curtidas: 46 vezes

Tutorial de ADO

Mensagempor frazato » 13 Jul 2015 14:50

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
#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

   
frazato
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 219
Data de registro: 08 Jul 2004 07:45
Curtiu: 0 vez
Mens.Curtidas: 4 vezes

Tutorial de ADO

Mensagempor JoséQuintas » 13 Jul 2015 15:11

A checagem seria no Open()

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:

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, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Tutorial de ADO

Mensagempor frazato » 13 Jul 2015 15:46

 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
frazato
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 219
Data de registro: 08 Jul 2004 07:45
Curtiu: 0 vez
Mens.Curtidas: 4 vezes

Tutorial de ADO

Mensagempor JoséQuintas » 14 Jul 2015 20:53

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, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18008
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1206 vezes

Próximo



Retornar para Contribuições, Dicas e Tutoriais

Quem está online

Usuários vendo este fórum: Nenhum usuário registrado online e 17 visitantes


Ola Amigo, espero que meu site e forum tem lhe beneficiado, com exemplos e dicas de programacao.
Entao divulgue o link da Doacao abaixo para seus amigos e redes sociais ou faça uma doacao para o site forum...
MUITO OBRIGADO PELA SUA DOACAO!
Faça uma doação para o forum
cron
v
Olá visitante, seja bem-vindo ao Fórum Clipper On Line!
Efetue o seu login ou faça o seu Registro