Quem é que nunca precisou , nunca utilizou um Arquivo Ini para carregar os parâmetros de uma conexão no DbExpress . Tudo muito bonito e prático , sem ter que recompilar a aplicação , só alterando o database no Arquivo Ini . Mas não se pode falar de parâmetros de conexão do DbExpress sem entender as propriedades LoadParamsOnConnect , DriveName , connectionName e os métodos Params.LoadFromFile e LoadParamsFromIniFile … Existe uma mágica por trás disso , e na maioria das vezes fazemos sem entender ou não querermos entender o que esta passando , bem ao estilo : ” já que deu certo é assim que eu vou fazer “. E vamos “simbora” para o mundo dos sem “Tempo” . Mas agora é a hora de mudar isto e evitar dores de cabeça no futuro .
No delphi crie novo projeto e adicione ao Form um Componente TButton. todos os exemplo abaixo poderão estar sendo programados no evento Onclick .
Declare na Uses da secção Interface ou implementation os namespaces DB, SqlExpr,dbxfirebird; Pois esteremos instanciando e configurando um objeto sqlconexao (tSqlConnection) em rumTime e precisaremos dessas unidades .
Obs) Aqui eu estarei utilizando o Delphi2010 .Para uma versão anterior do Delphi2010 a diferença esta no Nome do Driver e da respectiva Unidade que o Driver foi definido . Pode-se fazer todos os Teste escolhendo o DiverName Interbase (Nativo do Delphi) e definindo na Uses a Unidade DBXpress no lugar do dbxfirebird
Vamos começar com a propriedade LoadParamsOnConnect . Esta propriedade esta no Objecto inspector , e tem um impacto importante neste processo. O Padrão desta propriedade é False , mas quando cetada para True , o SqnConnection carrega para a propriedade params o Driver que esta definido na propriedade ConnectionName . Para isto este Driver deve existir no Arquivo dbxconnections.ini . Veja o exemplo abaixo
1)Exemplo com a Propriedade LoadParamsOnConnect cetada em True
var sqlConexao:TSQLConnection; begin sqlConexao:=TSQLConnection.Create(nil); try sqlconexao.Close; sqlconexao.ConnectionName:='EMPLOYEE_2_1.FDB'; sqlconexao.DriverName:='FIREBIRD'; sqlconexao.LoadParamsOnConnect:=true; sqlconexao.LoginPrompt:=false; sqlconexao.Open; showmessage(sqlconexao.Params.Text); //faça o Exemplo finally sqlConexao.Free; end; end;
ps)no meu caso particular eu tenho um Driver de Nome [EMPLOYEE_2_1.FDB] no Arquivo dbxconnections.ini
Perceba que o SqlConexao , procurou no Arquivo DBXCONNECTIOS.INI a definição do driver EMPLOYEE_2_1.FDB e carregou na propriedade params do SqlConexao . Alterando agora , esta propriedade para False , será nossa a responsabilidade de passar um Arquivo Ini Válido , para isto iremos carregar este Arquivo ini para a propriedade params do SqlConexao . Para fazer isto temos os métodos Params.LoadFromFile ou LoadParamsFromIniFile . Há uma diferença sutil e significativa entre eles . No diretorio do exe da aplicação defina um Arquivo Ini com as seguintes configuração . Salve este Arquivo com o Nome de Config.ini . Veja que este Driver tem um Nome , que no caso é [EXEMPLO.FDB] . “Guarde este nome pois iremos precisar dele”
[EXEMPLO.FDB] drivername=FIREBIRD blobsize=-1 commitretain=False Database=Coloque aqui um diretorio válido localecode=0000 password=masterkey rolename=RoleName sqldialect=3 isolationlevel=ReadCommitted user_name=sysdba waitonlocks=True trim char=False
Definido oArquivo Config.ini vamos as diferenças entre os métodos
2)Utilizando o Params.LoadFromFile
var sqlConexao:TSQLConnection; begin sqlConexao:=TSQLConnection.Create(nil); try sqlconexao.Close; sqlconexao.ConnectionName:='Qualquer_Nome';//não pode deixar em branco sqlconexao.DriverName:='FIREBIRD'; sqlconexao.LoadParamsOnConnect:=False; sqlconexao.Params.LoadFromFile('Config.ini'); //Arquivo Ini sqlconexao.LoginPrompt:=false; sqlconexao.Open; showmessage(sqlconexao.Params.Text); finally sqlConexao.Free; end; end;
3)Utilizando o LoadParamsFromIniFile(‘config.ini’);
var sqlConexao:TSQLConnection; begin sqlConexao:=TSQLConnection.Create(nil); try sqlconexao.Close; sqlconexao.ConnectionName:='Exemplo.FDB'; //Nome do Driver válido *** sqlconexao.DriverName:='FIREBIRD'; sqlconexao.LoadParamsOnConnect:=False; sqlconexao.LoadParamsFromIniFile('config.ini'); sqlconexao.LoginPrompt:=false; sqlconexao.Open; showmessage(sqlconexao.Params.Text); finally sqlConexao.Free; end; end;
perceba que a diferença é que o método LoadParamsFromIniFile so carrega para o Params se o Nome do Driver , que no nosso caso é [EXEMPLO.FDB] , for válido , Isto é , se existir o Alias [EXEMPLO.FDB] no Arquivo Config.Ini . Mas atenção , além desse quesito de “segurança” , existe ainda uma caracteristica mais importante neste método , que é a possibilidade de carregar para o params um Driver especifico . Vc pode ter no Arquivo Config.ini vários drivers criados definidos por vc , e em tempo de execução , escolher qual o driver que vc quer se conectar , so alterando o valor do sqlconexao.ConnectionName. Recapitulando : Assim como no Dbxconnections.ini tem vários drivers definidos , podemos ter também no config.ini varios drivers e escolher qual deles acessar com a propriedade sqlconexao.ConnectionName e carregando com o método LoadParamsFromIniFile .
Vamos agora entender a propriedade DriveName do SqlConnection . A principio é o nome do Driver que estamos utilizando , porém introduz no params algumas propriedades característica do Driver
Mas internamente qnd se atribui um nome de um Driver para esta propriedade , o delphi no método procedure TSQLConnection.SetDriverName(Value: string); faz uma série de operações , atribuições , comparações , de modo que ele “recria” o Params do Sqlconnection .
Agora PENSE e tente escolher qual das duas situações é mais indicado
var sqlConexao:TSQLConnection; begin sqlConexao:=TSQLConnection.Create(nil); try sqlconexao.Close; sqlconexao.ConnectionName:='Exemplo.FDB'; sqlconexao.LoadParamsOnConnect:=False; sqlconexao.DriverName:='FIREBIRD';//Antes de carregar o Params sqlconexao.LoadParamsFromIniFile('config.ini'); sqlconexao.LoginPrompt:=false; sqlconexao.Open; showmessage(sqlconexao.Params.Text); finally sqlConexao.Free; end; end;
e/ou
var sqlConexao:TSQLConnection; begin sqlConexao:=TSQLConnection.Create(nil); try sqlconexao.Close; sqlconexao.ConnectionName:='Exemplo.FDB'; sqlconexao.LoadParamsOnConnect:=False; sqlconexao.LoadParamsFromIniFile('config.ini'); sqlconexao.DriverName:='FIREBIRD';//Depois de carregar o Params sqlconexao.LoginPrompt:=false; sqlconexao.Open; showmessage(sqlconexao.Params.Text); finally sqlConexao.Free; end; end;
Ao fazermos Sqlconexao.DriverName:=’FIREBIRD’ após termos carregado o params por um dos métodos anteriores (LoadParamsFromIniFile , params.LoadFromFile) , estaremos recriando o params e com isto algumas definições serão sobre escritas . Por isto Sugerimos que a atribuição do Nome do Driver Ocorra antes de carregar os parâmetros com o Arquivo Ini , conforme estamos fazendo desde o inicio
Consideraçoes finais:
- A propriedade LoadParamsOnConnect em true o Driver carregado será do Arquivo dbxconnections
- A propriedade LoadParamsOnConnect em False o Driver carregado será definido por nos e carregado por um dos métodos (LoadParamsFromIniFile e/ou params.LoadFromFile)
- A diferença além da segurança entre o método LoadParamsFromIniFile do params.LoadFromFile é que o primeiro temos conduções de escolher qual o Driver que queremos acessar , basta definir corretamente a propriedade connectionName
- Por último vimos que o Nome do driver deve vir antes de carregar o params do sqnconection
Com isto terminamos este artigo , Lembrando que qualquer dúvida , opinião , manifestação estaremos de prontidão e aptos para receber qualquer tipo de crítica .espero ter sido útil agradeço a paciência , meu muito obrigado e atê a próxima .
Cara, parabéns pelo post. foi a melhor explicação para conectar com dbexpress no delphi 2010. vinha apanhando ,esse detalhe do LoadParamsOnConnect foi fundamental. parabéns!!
Olá Fernando tudo bem . Obrigado pela gentileza do feedback , fico feliz em ter lhe sido útil
Cara melhor tuto que eu ja vim show de bola, cara gostaria de saber no caso em que estou me conectando com zeos e mysql com fazer esta confuguração, se puder me ajudar agradeço muito
Ola Rosimario, quando conheci o DbEXpress no Delphi, investi todas as minhas fichas nele e não me arrempendi pois tem driver ate para o AZURE (atualissimo) e DataSnap . A evolução continua e cresecente do Dbexpress, me fez antenar cada vez mais para o seu aprendizado , não restando-me escolha em testar outras tecnologias de acesso. Sei que o Dbexpress tem algumas difiuldades com o mysql e o Zeos surgiu como alternativa , mas eu não instalei e nen baixei a biblioteca do Zeos. Me disponibilizo a prestar dentro das minhas limitações informaçoes sobre o Dbexpress , mas infelismente nada tenho a acrescentar sobre o Zeos . Muito obrigado e disponha
Olá MarcoSalles! De fato, parabéns não apenas pela didática e conhecimento mas, também pela maneira como direcionou o raciocínio e lógica do assunto mostrado. Mto bom, mesmo. Gostaria de aproveitar para perguntar-lhe o seguinte:
É possível, antes de Applcation.run, capturar o path da instalaçao feita pelo cliente e passar para o parâmetro do Database do connection.ini ou exemplo.ini.
É que gostaria de evitar que o cliente tivesse liberdade de instalar livremente o aplicativo e não precisasse configurar (ainda que fosse em um formulario de connection.database) os parâmetros em exemplo.ini
Muito obrigado.
Sergio Braga
Obrigado Sergio Braga a parte que me toca . Pois bem , quando vc se refere a path da aplicação vc esta se referindo ao caminho do executável certo ? Então a partir do delphi 2007 temos a variável
gsAppPath ( uses SWSystem delphi 2007 ,2009 , 2010 e Uses IWSystem delphiXe) . Para Alterar o DataBase do Arquivo Config.Ini que será posteriormente carregado pelo metodos LoadFromFile /ou LoadParamsFromIniFile com a propriedade LoadParamsOnConnect cetada em False , deveremos ler deste Arquivo ( Config.Ini ) esta propriedade . Para isto o delphi disponibiliza a classe TIniFile definida na uses IniFiles com propriedades e métodos (ReadString e WriteString) para estas e outras finalidades. A única ressalva que eu faço (pelo que eu entendi da sua dúvida inicial ) vc esta querendo colocar no dpr da Aplicação algo que verificasse e/ou modificasse o Valor do Database . Pois bem , não se deve dar mais responsabilidade a esta classe PROGRAM daquilo que ela foi inicialmete projetada . O que se faz e o que se recomenda em POO é criar uma classe especifica com esta tarefa. Tipo mais ou menos assim
Esta classe TConfigDefault é uma classe que tem um método Default com a responsabilidade de cetar o Valor do dataBase do Arquivo Config.Ini para o Valor definido por vc e caso de erro abortar a execução do programa ou comunicar através de mensagems possiveis error ..
Espeto ter entendido a sua dúvida , muito obrigado pelo feedback e caso vc tenha dificuldade em criar esta classe TConfigDefault eu tenho um exemplo desta classe pronta e posso estar lhe enviando
Não o faço aqui por motivo de espaço . att…
Ótimo artigo Marco Salles, mas estou com uma duvida, como faria pra encriptar a senha de acesso ao bando e se possivel encriptar tbm o localhost para que o user não tenha acesso. Vou explicar, é que hospedo os bancos de alguns de meus sistemas em um serviço de hospedagem, por conta disso eu deixo essas infos estaticas para que o user nao tenha acesso à essas infos (ja q se ele tiver a senha ele poderia acessar pelo painel de controle, tendo em vista que é a mesma senha, ao menos no uolhost é assim), estou tentando implementar uma criptografia ao menos para a senha. Vi que no FrameWork da Aquasoft eles tem essa funcionalidade, mas ainda nao consegui compreender para implementar no meu. valew pelo artigo.
Boa tarde Danilo , tudo bem? Então . antes de mais nada agradeço o seu apoio e seu incentivo .Sobre sua dúvida não é dificil conseguir a criptografia
Supondo que vc esteja no seguinte com a propriedade LoadParamsOnConnect cetada em False , e ao carregar as propriedades vc faz as alterações que julgar conveniente utilizando a intrução
SQLConnection1.Params.Values[‘Database’] := TClasseDescriptografa (SQLConnection1.Params.Values[‘Database’]);
Esta classe TClasseDescriptografa vc vai ter que desenvolver , ou procurar na net algo pronto … Mas a função dela é transformar o valor criptografado em um caminho um diretório válido
ps) Utilize a instrução entes de abrir a conexão
Resta para finalizar ao meu ver tres observações .
Nesta estrutura vc perde o poder de escrever diretamente no arquivo Ini a não ser que vc escreva de modo criptografado , o que acho impossivel ou no minimo muito dificil
Toda vez que for escrever no Arquivo ini vc tem que faze-lo utilizando a classe TClasseEncripografa , para que se possa descriptografa-lo depois
Vc pode fazer este processo para todas as outras variáveis mencionadas por vc como foi comentado sobre a senha
Tb há de se lembrar que muitas destas propriedades e paâmetros podem vir previamente carregadas junto no executável , sem ter que estar presentes no Ini
porém pode ser que com a engenharia reversa esses valores possam ser encontrados e acessados
Espero que vc tenha entendido e que eu possa ter sido claro. Se tiver alguma dúvida na implementação destas idéias ou não concorde ou tenha outro tipo de racicíneo esteja a vontade para opinir
[]sds
Boa tarde Marco, muito válido seu comentário, mas sabe o que eu fiz, usei sua dica 2) Utilizando o Params.LoadFromFile normalmente, mas criei uma pequena aplicação que encripta todo o arquivo (estou usando um arquivo xml), essa pequena aplicação fica a nivel de software house ou com o Administrador da empresa, assim os users não tem acesso ao conteudo do arquivo. O que eu fiz… antes de conectar eu chamo uma função que Decripta o arquivo xml.. e após a conexão no Finally ele Encripta novamente… funcionou legal.. agora para alterar algum parâmetro tem q usar a tal aplicaçãozinha “administrativa”, até achei interessante que podemos incluir nessa aplicação administradora outras configurações que ficam por conta da software house ou do Administrador do sistema… ficou ótimo… vlw
Valeu pela dica muito bom
Olá Carlos Luner , tudo bem ? Então , muito obrigado pelo seu incentivo . agradecido pelo comentário e feliz por ter lhe sido útil . Muito obrigado mesmo
[]sds
Aonde eu escrevo estas linhas
Pingback: Definir em RumTime ou passar como parâmetro o Caminho do Banco em DataSnap / DbxReader / DBX4 | Marco Salles
Tentei por alto adaptar do Cliente para o Servidor de DataSnap porem da o erro: “Item not found” e “argument out of range”
meu Config.ini esta assim:
[Exemplo.DataSnap]
DriverUnit=Data.DBXDataSnap
DriverAssemblyLoader=Borland.Data.TDBXClientDriverLoader,Borland.Data.DbxClientDriver,Versi
on=19.0.0.0,Culture=neutral,PublicKeyToken=91d62ebb5b0d1b1b
Port=211
HostName=127.0.0.1
CommunicationProtocol=tcp/ip
DatasnapContext=datasnap/
Filters={“ZLibCompression”:{“CompressMoreThan”:”1024″}}
e meu botao esta assim:
procedure TForm1.Button1Click(Sender: TObject);
var
sqlConexao:TSQLConnection;
begin
sqlConexao:=TSQLConnection.Create(nil);
try
sqlconexao.Close;
sqlconexao.ConnectionName:=’Exemplo.DataSnap’;
sqlconexao.LoadParamsOnConnect:=False;
sqlconexao.LoadParamsFromIniFile(‘config.ini’);
sqlconexao.DriverName:=’DataSnap’;//Depois de carregar o Params
sqlconexao.LoginPrompt:=false;
sqlconexao.Open;
showmessage(sqlconexao.Params.Text);
finally
sqlConexao.Free;
end;
end;
Aonde estou errando?
Vc tem que declara a Uses Data.SqlExpr, Data.DBXDataSnap ,IndyPeerImpl; para delphixe2
ps ) Meu Arquivo ini esta assim
[Exemplo.DataSnap]
drivername=DATASNAP
port=211
communicationprotocol=tcp/ip
hostname=localhost
Mas mesmo assim , testei com o seu Arquivo ini
[Exemplo.DataSnap]
DriverUnit=Data.DBXDataSnap
DriverAssemblyLoader=Borland.Data.TDBXClientDriverLoader,Borland.Data.DbxClientDriver,Versi
on=19.0.0.0,Culture=neutral,PublicKeyToken=91d62ebb5b0d1b1b
Port=211
HostName=127.0.0.1
CommunicationProtocol=tcp/ip
DatasnapContext=datasnap/
Filters={“ZLibCompression”:{“CompressMoreThan”:”1024″}}
e funcionou sem problemas ..
Não esqueça que o servidor tem que estar RODANDO
[]sds e qq dúvida volte a postar
Não funcionou ainda, porem em vez de dar os 2 erros mencionados, so da o primeiro “Item not found” e fiz mais um teste, eu adicionei um sqlconnection no form e configurei o driver para datasnap e compilei e ele adicionou mais essas duas “IPPeerClient, Data.DBXCommon”, mas mesmo assim nao funciona!
Entendo … Mas vc testou com o config do modo tradicional do delphi com essas configurações
[Exemplo.DataSnap]
DriverUnit=Data.DBXDataSnap
Port=211
HostName=127.0.0.1
CommunicationProtocol=tcp/ip
refis meus teste com este config e continuou sem erro
Por gentileza , refaça os teste e nos comunique
[]sds
Sim fiz desse modo tambem, agora outra coisa que ficou mais estranho foi que eu peguei um sqlconnection e deixei ele todo configurado e quando eu testo a conexao dele com o server datasnap dentro do delphi ela conecta ok, ae se eu pegar da um F9 do jeito que ta quando abre o programa sem eu simplesmente executar qualquer comando ele da o erro que desde o inicio eu estou mencionando, so que no meu projeto mesmo que tem o clientmodule esta ok so q a conexao não é dinamica, é fixa. nesse projeto que fiz so pra teste mesmo so deixo o server rodando e criei um projeto em branco e adicionei os codigos conforme o artigo!
So mais uma coisa eu uso delphi XE5!!
Aleluia, até que enfim consegui resolver… descobri o que era, como vc falou que tinha que adicionar nas Uses , eu fui e adicionei aquelas que vc falou e mesmo assim nao tinha dado certo… porem como no servidor eu adicionei filtros eu percebi que no meu projeto no ClientModule tinha adicionado essa aqui: DBXCompressionFilter. depois que coloquei ela parou de dar o erro, se não tivesse falado a respeito das Uses jamais imaginaria que poderia ser, muito obrigado pelo artigo que foi de muita valia e pela paciência em me ajudar!!!
Obrigado pelo seu feedback… Percebi que vc esta trabalhando com servidor .. Vc esta utilizando DbxReader ou esta utilizando as classes RAD do delphi mesmo ????
Olá,
queria tirar uma duvida, se eu já coloco o componente no DataModule em qual evento eu coloco para carregar o arquivo INI? É possivel carrega pelo INI nome do SGDB e nome da conexão? Uso MySQL?
Agradeço desde já, tirou muitas duvidas.
Uso MySQL.
Bem , depende muito do sua arquitetura … Já tentou no momento da criação do DataModulo ??? OnCreate ????
[]sds e obg
Olá consegui colocando no oncreate, colocando sqlconexao.LoadParamsFromIniFile(‘config.ini’);
, carrego o driver, nome da conexão, etc. Porém tive que deixar a opção sqlconexao.LoadParamsOnConnect:=False;
Ok …
sqlconexao.LoadParamsOnConnect:=False conforme sugerido pelo artigo ???
Olhe as considerações finais
◾A propriedade LoadParamsOnConnect em true o Driver carregado será do Arquivo dbxconnections
◾A propriedade LoadParamsOnConnect em False o Driver carregado será definido por nos e carregado por um dos métodos (LoadParamsFromIniFile e/ou params.LoadFromFile)
Se LoadParamsOnConnect em true o Driver já deve ser pre compilado junto ao executável .. OK ???
Olá Marco deixe eu explicar direito, minha arquitetura é em multitier com o datasnap. Estou tentando carregar minhas configurações ini utilizando LoadParamsFromIniFile, se eu deixar as propriedades do sqlconexao sem nada e colocar no oncreate do datamodule para carregar via ini, simplesmente ele da aviso e pede as informações, isso com o LoadParamsOnConnect:=False ou True. Se eu colocar no sqlconexao apenas o nome da conexão e deixar LoadParamsOnConnect:=TRUE o arquivo ini é carregado, e não o dbxconnections, se deixar false da erro novamente. Então o que queria era carregar tudo via ini até o nome da conexão.