Meu uso 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

Meu uso de ADO

Mensagem por JoséQuintas »

É só um comentário sobre meus fontes, que devo postar de vez em quando.
Meu uso de ADO parece ADO... mas não é

É que uso uma classe intermediária.
Até poderia alterar o ADO original da Microsoft, pelo Harbour, mas preferi assim.

O ADO tem Eof(), MoveNext(), Fields(), Move(), etc. e minha classe também, apenas não é diretamente a função do ADO.

Código: Selecionar todos

oTemporario := oConexao:Execute( "SELECT NOME FROM CLIENTES WHERE CODIGO=1" )
Isso teoricamente retorna um recordset ADO, mas na prática não é totalmente verdade.
Se não tem nada, não retorna nada, NIL, nada mesmo, não um recordset com zero registros.
Se não tem conteúdo, como é que vai criar uma estrutura pra um retorno sem nenhum campo?
É... porque se SELECT é pra pesquisar campos diversos, como pode existir uma estrutura pré-definida pra não se sabe o que?

Pois é...
Por isso eu criei a classe temporária.

Testar EOF() em nada... não dá.
Seria algo como NIL:Eof()

Imagine em tudo que é fonte, ficar testando se o retorno é NIL, se o campo existe pra não dar erro, se tem conteúdo antes de testar EOF(), etc. etc. etc.
Complicado... então criei a classe intermediária que evita todos esses erros, e toda necessidade dessa checagem, porque ela já faz.

A classe, de certa forma, é relativamente simples: tem o recordset, e tem funções que são repassadas ao recordset.

Código: Selecionar todos

CLASS ADOClass
   VAR oRecordset
   METHOD Eof()  INLINE ::oRecordset:Eof()
   METHOD MoveNext() INLINE ::oRecordset:MoveNext()
ENDCLASS
Acima apenas exemplo inicial.
EOF() da classe vai testar EOF() no recordset.

Como eu disse antes, se testar eof() em vazio dá erro.
Com a classe intermediária, basta eu fazer isso na classe.

Código: Selecionar todos

METHOD Eof() INLINE iif( ::oRecordset == Nil, .T., ::oRecordset:Eof() )
Pronto, acabei com a necessidade de gambiarras em fontes pra teste adicional, basta eu usar essa classe intermediária.

Outro problema: MoveNext(), que seria o SKIP do DBF, dá erro se já estiver em EOF() e tentar pular para o próximo registro.
E também dá erro se fizer no arquivo vazio (NIL).
Vai precisar de 2 testes adicionais, os mesmos do EOF() e mais um pra testar EOF().
Mas dá pra aproveitar o que já existe, de eof()

Código: Selecionar todos

METHOD MoveNext() INLINE iif( ::oRecordset:Eof(), Nil, ::oRecordset:MoveNext() )
Pronto, problemas resolvidos.
Não vai dar erro se for Nil, também não vai dar erro se já estiver em Eof().

E por aí vai.
Foi pra isso que criei a classe intermediária, pra não precisar ficar tratando erros em tudo que é fonte.

Poderia alterar o nome de MoveNext() pra Skip(), pra ficar igual DBF, mas preferi deixar com o nome original.

Também embuti a conexão como parte da classe, mais o método Execute(), e também teste pra verificar se deu erro no execute, pegando mensagem de erro do ADO.

Por isso, quando ver fontes que eu posto, pode dar a impressão de que essa parte é tratada automaticamente pelo ADO, mas não é.

Código: Selecionar todos

cnSQL := ADOLocal() // deixei de usar ADOClass():New( AppConexao() )
WITH OBJECT cnSQL
   :Execute( "SELECT CODIGO FROM CLIENTES" )
   DO WHILE ! :Eof()
      ? :Number( "CODIGO" ), :String( "NOME" )
      :MoveNext()
   ENDDO
   :CloseRecordset()
ENDWITH
Fica meio parecido com ADO, mas não é exatamente/diretamente o ADO.
Em ADO seria mais como isto:

Código: Selecionar todos

cnSQL := win_OleCreate( "ADODB.Connection" )
cnSQL:.....
cnSQL:Open()

oRs := cnSQL:Execute( "SELECT ..." )
WITH OBJECT oRs
   DO WHILE ! oRs:Eof()
      ? :Fields( "CODIGO" ):Value, :Fields( "NOME" ):Value
      :MoveNext()
   ENDDO
   :Close()
ENDWITH

cnSQL:Close()
Como eu disse, parece... mas não é.
Nesse fonte faltaria o teste de Nil, por exemplo, que minha classe intermediária acaba tornando desnecessário.

NÃO SEI o que acontece na SQLMIX num caso desses, porque provavelmente deve acontecer também, do MySQL não retornar NADA.
Apenas comentário, NÃO estou falando nada contra, apenas é um comentário de que realmente não sei como isso é tratado.
No caso do ADO dá erro, é a classe que criei que evita dar erro, ou testes que sejam colocados nos fontes.

E voltando à minha classe....
Aproveitei pra adicionar recursos, que já postei por aqui, como o :ReturnSelect( "SELECT 1" )
Isso evita muito fonte adicional.

E é por aí que a gente vai simplificando nossa vida... (ou às vezes complicando) kkkk
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

Meu uso de ADO

Mensagem por JoséQuintas »

Já pensei em criar a conexão aí dentro como CLASSVAR.
É que ao criar uma instância, a conexão seria mantida.
Mas... não uso só pra MySQL, e nem só pra um servidor, então o CLASSVAR poderia trazer problemas.

Digamos que CLASSVAR é como se fosse uma variável pública, que se mantém fixa ao criar mais objetos pra classe.

A HWGUI, por exemplo, usa esse recurso para que qualquer window contenha a lista de todas as window do aplicativo.
Pra isso, aWindowList é do tipo CLASSVAR.
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