Framework DBX (Metadata)
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!
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
Curtidas 0
Respostas
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!
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
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...
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
18/10/2011
Alguém se habilita?
GOSTEI 0
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
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
18/10/2011
Eu confesso que tentei e não descobri como é.
Deveria ser algo assim:
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.
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
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
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
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