• Nenhum resultado encontrado

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

N/A
N/A
Protected

Academic year: 2021

Share "Um aplicativo VFP/SQL SERVER do início ao fim - Parte 04"

Copied!
6
0
0

Texto

(1)

Frederico Tomazzeti Terça-feira, 05 de setembro de 2006

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

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

(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

(3)

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

(4)

_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 aStored Procedureque retorna um contador sequencial da tabelaContadordo 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

(5)

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

(6)

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.

Referências

Documentos relacionados

Assim, podemos usar a palavra “cerrado” em três sentidos: 1) Cerrado, com a inicial maiúscula, quando estivermos nos referindo ao domínio fitogeográfico do Cerrado, incluindo

Foram executadas incubações a 5 m de profundidade, em frasco tipo DBO, de Oozooides da Salpa Thalia democrática com fitoplâncton coletado no mesmo local para as estimativas de

Para os demais casos, não aludidos no subitem 24.1, a inexecução parcial do ajuste ou a execução parcial em desacordo cora a ARP implica no pagamento de multa de 30% (trinta por

III - para efeito deste Regulamento, a graduação alcoólica de vinhos e derivados da uva e do vinho será expressa em porcentagem de volume de álcool etílico à temperatura de vinte

Tendo em vista ter sido protocolizado na ALADI, em 18 de outubro, o Acordo de Complementação Econômica 58, entre o Mercosul e o Peru, estamos informando o cronograma de

Durante la combustione nello stato NORMALE il sistema può passare in MODULAZIONE se: • la temperatura fumi supera il valore ottimale nella condizione di funzionamento.. • o

Como resposta aos objetivos propostos o trabalho identificou formas de abordagem à SCRM e uma estrutura lógica para a gestão dos riscos em cadeia de suprimentos composta pela

Sintomas/lesões em caso de inalação : Em condições normais de utilização, não se prevê um perigo significativo de inalação.. Sintomas/lesões em caso de contacto