Quantcast
Channel: » Frederico Tomazzeti
Viewing all articles
Browse latest Browse all 5

Um aplicativo VFP/SQL SERVER do início ao fim – Parte 04

$
0
0

Um aplicativo VFP/SQL SERVER do início
ao fim – Parte IValguns conceitos básicos sobre acesso ao SQL SERVER utilizando
OLEDB/ADO. Para isso vou mostrar algumas funções e comentar cada uma delas.


Neste artigo as coisas parecerão um pouco confusas, pois quero
passar


Estas funções serão utilizadas posteriormente na sequência dos
artigos. Elas serão a base para um futuro componente “midle tier” (camada
do meio) de um sistema Cliente/Servidor.


O início


Para acessar um banco de dados diferente do banco nativo do VFP, precisamos
de uma string de conexão, como vimos no final do terceiro artigo, porém
geralmente precisamos configurar o nome do servidor, nome do banco, tipo de
login, etc.


Para isso vamos utilizar um arquivo .INI que, nada mais é do
que um arquivo texto (feito no bloco de notas) que possui alguns parâmetros
e, a rotina abaixo irá ler estes parâmetros.


O arquivo UTMAG.INI possui estas linhas:


[UTMAG]
servidor=SRVUTMAG
banco=UTMAG
autolog=S


O código abaixo fará parte do PRG inicial do sistema. Este código cria
propriedades em _SCREEN, que é visível em todo o sistema, evitanto assim criar
variáveis públicas. Desta forma, podemos mudar o nome do servidor ou do banco
de dados sem precisar recompilar nosso sistema, basta alterar o arquivo .INI.

A opção “Autolog” irá determinar mais adiante se utilizaremos o login
integrado com o Windows, esta opção só é possível se você utilizar Windows NT
(Windows 2000) tanto no servidor (2000 server) quanto nos terminais (2000
professional) pois esta versão do sistema possui login integrado com outros
aplicativos, se você possuir Windows 95, 98 ou millenium você deverá utilizar
“AUTOLOG=N” e durante a inicialização do sistema pedir ao usuário que digite
login e senha para acesso ao SQL SERVER. Mais adiante veremos isso.

Este é o código que irá ler os dados em UTMAG.INI.

_Screen.AddProperty("servidor",”)
_Screen.AddProperty("banco",”)
_Screen.AddProperty("integrado",”)
_Screen.AddProperty("usuario",”)

* Buscar os dados do arquivo UTMAG.INI – parâmetros
* 1 – secção o que fica entre colchetes [ARQUIVO]
* 2 – Variável nesta secção
* 3 – opção padrão caso não encontre
* 4 – variável que receberá o valor passada por referência
* 5 – quantidade de caracteres que a variável receberá
* 6 – arquivo .ini

Declare Integer GetPrivateProfileString In Win32API As GetPrivStr ;
STRING cSection ,;
STRING cKey ,;
STRING cDefault ,;
STRING @cBuffer ,;
INTEGER nBufferSize ,;
STRING cINIFile

lcServidor = Space(20)
lcBanco = Space(20)
lcIntegrado = Space(10)

GetPrivStr(‘dt_sistemas’, ‘servidor’ ,’vazio’, @lcServidor , 20,
‘outros\dt.ini’)
GetPrivStr(‘dt_sistemas’, ‘banco’ ,’vazio’, @lcBanco , 20,
‘outros\dt.ini’)
GetPrivStr(‘dt_sistemas’, ‘autolog’ ,’vazio’, @lcIntegrado , 10,
‘outros\dt.ini’)

_Screen.servidor = Left(lcServidor, Len(Alltrim(lcServidor)) – 1)
_Screen.banco = Left(lcBanco, Len(Alltrim(lcBanco)) – 1)
_Screen.integrado= Left(lcIntegrado, Len(Alltrim(lcIntegrado)) – 1)



O pequeno trecho de código abaixo guarda qual o nome do usuário que está
logado, esta informação será utilizada posteriormente em confirmações de login
integrado.
lcNome = Sys(0)
lnPosicao = At(‘#’,lcNome) + 2
lnTamanho =Len(lcNome) – At(‘#’,lcNome) -1
_Screen.usuario = Substr(lcNome,lnPosicao,lnTamanho)


O acesso ao banco e as regras de negócio

O código abaixo irá criar nossa classe de acesso a dados, que irá aumentar
bastante durante o desenvolvimento do sistema. Vou mostrar apenas o básico para
não complicar muito agora, pois quando você estiver transformando seu sistema
para Cliente/Servidor você obviamente utilizará a sua estrutura já existente.

Define Class UtmagDados As Relation OlePublic

lors = Null
loConn = Null
cMensError = ”
nNativeError = 0

Protected cStringSql,;
cServerName,;
cDataBaseName,;
cIntegrado ,;
cUserID,;
cPwd,cConnectionString,;
cCampos,cValor,cCamposSimples,cSqlWhere

Procedure Init (
pServidor As String, ;
pBanco As String, ;
pIntegrado As String, ;
pUsuario As String, ;
pSenha As String )

With This
.cIntegrado = Alltrim(pIntegrado)
.DefineAtributoConexao(pServidor, pBanco, pUsuario,
pSenha)
.cStringSql = ""
.cConnectionString = ""
.loConn = Null
.lors = Null
Endwith
Endproc

Procedure Error
Lparameters nError, cMethod, nLine
If This.loConn.Errors.Count>0
This.cMensError = "Numero do Error: " + ;
Transform(This.loConn.Errors.Item(0).NativeError)
+ Chr(13) + ;
"Descricao Error: "+This.loConn.Errors.Item(0).
Description + Chr(13) +;
"Origem do Error: "+This.loConn.Errors.Item(0).Source
Else
This.cMensError = "Numero do Error: "+Transform(nError)
+ Chr(13) +;
"Mensagem do Error: "+Message( ) + Chr(13) +;
"Linha do Error: "+Transform(nLine) + Chr(13) +;
"Metodo: "+cMethod
Endif
Endproc

Procedure Destroy
With This
If Vartype(.loConn) = "O"
.Desconectar()
Endif
Endwith
Endproc

*************************************************************
* Procedure: DefineAtributoConexao
* Objetivo: Inicializa os atributos para a conexão com BD
* Esses dados na verdade virao de um Objeto publico que
* Contem Os dados para conexao com o BD
*************************************************************
Procedure DefineAtributoConexao ( ;
pServidor As String, ;
pBanco As String, ;
pUsuario As String, ;
pSenha As String )

With This
.cServerName = Alltrim(pServidor)
.cDataBaseName = Alltrim(pBanco)
.cUserID = Alltrim(pUsuario)
.cPwd = Alltrim(pSenha)
Endwith
Endproc


O Procedimento abaixo faz a conexão com o banco de dados, observe a
condição: IF .cIntegrado = ‘S’ – Aqui utilizamos a conexão integrada com o
Windows ou não.
   *************************************************************
* Procedure: Conectar
* Objetivo: Fazer a conexão com o banco de dados via ADO
*************************************************************
Procedure Conectar (pConnectionString As String ) As Boolean
Local llOK
With This
If Type("pConnectionString") = "C"
*– Passou a String de conexao por parametro
.cConnectionString = pConnectionString
Else
If .cIntegrado = ‘S’
* string pra conexão através do login do win2000

               .cConnectionString = ‘Provider=SQLOLEDB.1′    +;
‘;Integrated Security=SSPI’ +;
‘;Persist Security Info=False’ +;
‘;Initial Catalog=’ + .cDataBaseName +;
‘;Data Source=’ + .cServerName
Else
* string para conexão de segurança mista
* exige usuário digitar login e senha
.cConnectionString = ‘Provider=SQLOLEDB.1′ +;
‘;Data Source=’ + .cServerName +;
‘;trusted_connection=false;’ +;
‘;Initial Catalog=’ + .cDataBaseName +;
‘;User ID=’ + .cUserID +;
‘;PassWord=’ + .cPwd
Endif
Endif
.loConn = Createobject("adodb.connection")
If Vartype(.loConn) = "O"
.loConn.Open(.cConnectionString)
If .loConn.State = 1 && Conexao Aberta
llOK = .T.
Else
llOK = .F.
Endif
Endif
Endwith
Return llOK
Endproc

Esta procedure desconecta o sistema do banco de dados:
   *************************************************************
* Procedure: Desconectar
* Objetivo: Fecha a conexão com o banco de dados via ADO
*************************************************************
Procedure Desconectar
With This
If Vartype(.lors) = "O"
If .lors.State # 0
.lors.Close()
Endif
Endif
If Vartype(.loConn) = "O"
If .loConn.State # 0
.loConn.Close()
Endif
Endif
.loConn = Null
.lors = Null
Endwith
Endproc


Os dois procedimentos seguintes criam e fecham a conexão com o banco de
dados, pois não é necessário trabalhar sempre conectado. Desta forma, podemos
maximizar o acesso ao banco. Imagine um terminal que é utilizado apenas a cada 30
minutos, não há necessidade de haver uma conexão permanente deste terminal com o
banco.

É uma questão de economia, pois o seu cliente compra uma quantidade “X” de
licenças de acesso a banco, e só pode utlizar esta quantidade, desta forma
podemos multiplicar acessos com um mesmo número de licenças.

*************************************************************
* Procedure: CriaConexao
* Objetivo: Cria uma conexao publica onde todos os form’s
* compartilharao acesso dessa conexao.
**************************************************************
Procedure CriaConexao
_Screen.omanipuladados = Createobject("ManipulaDados",
_Screen.servidor,;
_screen.banco,;
_screen.integrado,;
_screen.usuario,;
_screen.senha)
*– Estabeleca a conexao com o BD
_Screen.omanipuladados.conectar()
Endproc

*************************************************************
* Procedure: FechaConexao
* Objetivo: Fecha uma conexao publica
**************************************************************

Procedure FechaConexao
If Vartype(_Screen.omanipuladados) = "O"
_Screen.omanipuladados.Desconectar()
_Screen.omanipuladados = Null
Endif
Endproc


Os 3 procedimentos seguintes serão utilizados para transações, quem já
utilizou o DBC do FOX já está familiarizado com transações (Begin Transaction, End Transaction, Rollback, etc).
   *************************************************************
* Procedure: IniciarTransacao
* Objetivo: Abre um transact pelo ADO
*************************************************************

Procedure IniciarTransacao
This.loConn.BeginTrans
Endproc
*************************************************************
* Procedure: EncerrarTransacao
* Objetivo: Encerra um transact pelo ADO
*************************************************************

Procedure EncerrarTransacao
This.loConn.CommitTrans
Endproc

*************************************************************
* Procedure: AbortarTransacao
* Objetivo: Aborta um transact pelo ADO
*************************************************************

Procedure AbortarTransacao
This.loConn.RollBackTrans
Endproc


Estes dois últimos procedimentos são utilizados para executar a Stored Procedure que retorna um contador sequencial da tabela Contador do nosso banco
de dados.
   *************************************************************
* Procedure: ObterNovoContador
* Objetivo: Retorna contador único conforme stored procedure
*************************************************************
Procedure ObterNovoContador As Integer
*– Obtem o ID_UNICO do Sistema
Return This.executarSP("obternovooid",0,"",1,"@nRetorno")
Endproc

*************************************************************
* Procedure: ExecutarSP
* Objetivo: função para executar stored procedures no banco
* Parametros: pNomeDaSP – nome da stored procedure
* pNroParEnt – quantidade de parâmetros de entrada da SP
* pParEntrada – parâmetros de entrada, iniciando com
* arroba e separados por virgula
* pNroParSai – Quant. de parâmetros de saida – por
* enquanto só pode ser 1 ou zero
* pParSaida – parâmetro de saída iniciando com arroba
*************************************************************
Procedure executarSP As Custom
Parameters pNomeDaSP, pNroParEnt, pParEntrada, pNroParSai,
pParSaida

* declaração de variáveis locais
Local loADOCmd, loADOParam && objetos

Local adInteger, adCurrency, adDate ,;
&& uso do ADO
adBoolean, adChar, adNumeric, adVarChar,
AdParamInput ,;
adParamOutPut, adCmdStoredProc, AdExecuteNoRecords

Local lnTamanhoString, laEntradas, laSaidas,
lnElementoMatriz, ;
lcGuardarString && uso interno da função
Local lnRetorno,i,llConectou


* valores utilizado pelo ADO
adInteger = 3
adCurrency = 6
adDate = 7
adBoolean = 11
adChar = 129
adNumeric = 131
adVarChar = 200
AdParamInput = 1
adParamOutPut = 2
adCmdStoredProc = 4
AdExecuteNoRecords = 128
If Vartype(This.loConn) # "O"

*– Se nao houver conexao estabelece a conexao
If !This.Conectar()
Return .F.
Else
llConectou = .T.
Endif
Endif
loADOCmd = Createobject("ADODB.Command")
loADOCmd.ActiveConnection = This.cConnectionString

loADOCmd.CommandText = pNomeDaSP
loADOCmd.CommandType = adCmdStoredProc


* criar parametros de entrada
If pNroParEnt > 0 && monta um array com os
parametros de entrada
lnTamanhoString = Len(pParEntrada)
Dimension laEntradas(pNroParEnt)
lcGuardarString = ”
lnElementoMatriz = 1

         For i = 1 To lnTamanhoString
If Substr(pParEntrada,i,1) = ‘,’
laEntradas(lnElementoMatriz) = lcGuardarString
lnElementoMatriz = lnElementoMatriz + 1
lcGuardarString = ”
Else
lcGuardarString = lcGuardarString +
Substr(pParEntrada,i,1)
Endif
Next
laEntradas(lnElementoMatriz) = lcGuardarString

For i = 1 To pNroParEnt
loADOParam = loADOCmd.CreateParameter(laEntradas(i),
adVarChar, AdParamInput)
loADOCmd.Parameters.Append(loADOParam)
Next
Endif


* criar parametros de saída (retorno da stored procedure)
If pNroParSai > 0
lnTamanhoString = Len(pParSaida) && monta um array com
os parametros de saida
Dimension laSaidas( pNroParSai)
lcGuardarString = ”
lnElementoMatriz = 1
For i = 1 To lnTamanhoString
If Substr(pParSaida,i,1) = ‘,’
laSaidas(lnElementoMatriz) = lcGuardarString
lnElementoMatriz = lnElementoMatriz + 1
lcGuardarString = ”
Else
lcGuardarString = lcGuardarString +
Substr(pParSaida,i,1)
Endif
Next
laSaidas(lnElementoMatriz) = lcGuardarString

For i = 1 To pNroParSai
loADOParam = loADOCmd.CreateParameter(pParSaida,
adInteger, adParamOutPut)
loADOCmd.Parameters.Append(loADOParam)
Next
Endif
loADOCmd.Execute(,,AdExecuteNoRecords)
lnRetorno = loADOCmd.Parameters(pParSaida).Value

loADOCmd = Null
If llConectou
This.Desconectar()
Endif

If pNroParSai = 1
Return lnRetorno
Else
Return -1
Endif
Endproc
EndDefine



As coisas parecem um pouco fora do lugar neste momento mas são estes
procedimentos (e outros de menor relevância que veremos com a sequência dos
trabalhos) que fazem todo o trabalho de acesso e manipulação de dados.

É fundamental estudar ADO, para isso recomendo os artigos da MSDN sobre o
assunto e um livro que me ensinou muito foi “Dominando SQL Server 2000 – A
Biblia”.

Outro livro que auxiliará bastante, principalmente na quinta parte deste
artigo é o “Desenvolvendo soluções XML com Visual FoxPro” do nosso colega Fábio
Vazquez.

Por fim, agradeço ao Breno Viana, nosso colega de UT e meu colega de trabalho,
pois tem muita coisa dele nas funções que apresentei aqui.

O post Um aplicativo VFP/SQL SERVER do início ao fim – Parte 04 apareceu primeiro em .


Viewing all articles
Browse latest Browse all 5