Framework DBX (Metadata)

Delphi

18/10/2011

Utilizando o Delphi XE com Firebird e MSSQL, decidimos embutir o script de criação e atualização do banco de dados no executável da aplicação, e frente a isso, fazer isso das classes DBX Metadata.

Acontece que não encontramos um modo de atualizar tabelas já existentes na base de dados, apenas criar novas. Nos testes que realizamos, o comando CreateTable do provider apenas (e realmente) cria a tabela, não conseguindo nós criar novas colunas em tabelas existentes.

Existe o comando AddColumn, mas este cria o vínculo da coluna apenas em memória, cabendo ao provider (TDBXMetadataProvider) aplicar essas atualizações ao BD.

Mas quando temos uma tabela já existente na base de dados, e precisamos adicionar uma nova coluna, índice, chaves, etc., temos que no final, aplicar essa atualização com o comando CreateTable, presente no provider, mas que é gerada uma exceção se a tabela já existe...

Precisaria de algo como ALTER TABLE, ou falando em método, algo como UpdateTable, para aplicar as mudanças.

Acreditem, já procuramos bastante, mas os exemplos demonstram apenas a criação do banco de dados, mas não apresentam a devida manutenção do dia-a-dia...

Penso que, se não há um modo de fazer isso, se ninguém faz essas atualizações COM O FRAMEWORK, de nada vale o recurso de metadata, se foge as situações reais e necessárias do dia-a-dia. O que acham?

Alguém utiliza DBX metadata no dia-a-dia? Alguém passou por isso, ou tem essa experência?

Obrigado!
Guess Me

Guess Me

Curtidas 0

Respostas

Gustavo Bretas

Gustavo Bretas

18/10/2011

Olá, bom dia!

Eu ainda não tinha ouvido falar desse recurso no dbExpress!!

Mas sou adépto a enviar o script junto com o executável, na primeira vez que precisei, criei o mecanismo do zero!
Inicialmente foi desenvolvido para SQL Server, mas depois um amigo tbm precisou e adaptou para o Firebird.

Pode parecer estranho, mas ficou muito funcional, eu criei um Form, e cada script de versão fica em um Memo, mas como a query não suporta comitar todo o script, eu separo os blocos com o termo GO sozinho na linha, então uma função lê o que esta no Memo até encontrar o termo, comita e começa denovo.

No SQL Server vc tem a liberdade de fazer as verificações de existencia de tabela, colunas, etc, antes de enviar o comando para criar o objeto, então ficou tranquilo, já no Firebird vc não consegue fazer um IF e o comando junto, então ficou um pouco mais limitado, eu até pensei em desenvolver uma forma de fazer ele chegar usando Tags, mas o script de versão roda apenas uma vez e não tive tempo.

Aí vc vai questionar, mas vai chegar uma hora que vai ter dezenas de Memos no Form!! É verdade, nem tudo na vida são flores... rs! Eu deixava uma média de 15 scripts nele, os antigos deletava.
Até mesmo por que mantinha uma base atualizada para a implantação de novos clientes, então os scripts antigos ficaram apenas documentados, mas fora do executável.

Só pra finalizar, talvez haja maneiras melhores e mais eficientes, mas tbm uma coisa simples pode resolver seu problema, pensa ae! Abraço!
GOSTEI 0
Guess Me

Guess Me

18/10/2011

Então, a algumas versões do delphi através, é possível fazer isso através do novo (que já não é tão novo assim) dbExpress.

Uma das vantagens mais interessantes, é o fato de podermos esquecer aquelas pequenas variações de nomenclaturas, e comandos de cada SGBD, pois o próprio recurso de metadata do DBX gerencia isso.

Algo como o parecido abaixo é possível ser feito:

Provider: TDBXDataExpressMetaDataProvider;
Table: TDBXMetaDataTable;
Id: TDBXInt32Column;
Text: TDBXUnicodeVarCharColumn;
begin
Provider := DBXGetMetaProvider(conn.DBXConnection);

Table := TDBXMetaDataTable.Create;
Table.TableName := TABLENAME;

Id := TDBXInt32Column.Create(TABLEID);
Id.Nullable := false;
Id.AutoIncrement := true;

Text := TDBXUnicodeVarCharColumn.Create(TABLETEXTFIELD, 40);
Text.Nullable := False;

Table.AddColumn(Id);
Table.AddColumn(Text);

Provider.CreateTable(Table); <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
AddPrimaryKey(Provider, Table.TableName, ...);


Extremamente útil, mas até agora na teoria, pois o nosso problema está exatamente na linha apontada... (<<<<<) Já tentamos fazê-lo funcionar com a tabela já existente, mas é gerada uma exceção...
GOSTEI 0
Guess Me

Guess Me

18/10/2011

Alguém se habilita?
GOSTEI 0
Gustavo Bretas

Gustavo Bretas

18/10/2011

Rapaz, eu estava olhando o código dessa classe aqui, realmente é bem complicado, estou achando mais fácil vc criar um compoente para fazer o que vc precisa do que usá-lo... rs!

Mas veja a classe TDBXMetaDataProvider tem o método MakeAlterTableSql, talvez ele te ajude.

Aqui no Delphi XE as units estão na pasta C:\Program FIles (x86)\Embarcadero\RAD Studio\8.0\Source\Database
GOSTEI 0
Vitor Rubio

Vitor Rubio

18/10/2011

Eu confesso que tentei e não descobri como é.

Deveria ser algo assim:


  provider.Execute(Provider.MakeAlterTableSql(Table.TableStorage, Table.ColumnsStorage));


como é feito no próprio método CreateTable, mas recebo a exception de unsuported operation. Simplesmente ele não faz nada quando é para alterar uma tabela adicionando um campo. Alguém tem alguma idéia?

Acho que para resolver isso não vai ter outra maneira, será necessário montar o script de alter table.
GOSTEI 0
Guess Me

Guess Me

18/10/2011

Pois é, havíamos dado uma olhada no método MakeAlterTable, mas sem sucesso também.. seria uma melhor opção não utilizá-lo? Lamentável...
GOSTEI 0
Louremberg Almeida

Louremberg Almeida

18/10/2011

essa função Provider.MakeAlterTableSql(Table.TableStorage, Table.ColumnsStorage)
apenas
altera o nome da tabela
altera visão
altera indice
altera chave estrangeira
mas não cria campo
por isso cria a exceção quando
mandamos utilizar essa função
GOSTEI 0
POSTAR