Um conhecimento só é válido quando compartilhado.

quarta-feira, 23 de novembro de 2016

ORMBr - Conhecendo o Outro Lado

Seja bem vindo, e ótima leitura. 
O combustível do ORMBr sempre será as classes modelos, e para que tenhamos alto desempenho, precisamos conhecer o que adicionar a esses modelos para que tenhamos sincronização com nosso banco de dados.
Apresento aqui para vocês as correspondências entre os tipos usados pelo ORMBr e os tipos criados no seu banco dados já existente.



procedure TFieldTypeRegister.GetFieldTypeDefinition(AColumn: TColumnMIK);
begin
  case AColumn.FieldType of
    ftByte, ftShortint, ftSmallint, ftWord:
    begin
      AColumn.TypeName := 'SMALLINT';
    end;
    ftInteger, ftLongWord:
    begin
      if      FDriverName = dnMSSQL then AColumn.TypeName := 'INT'
      else if FDriverName = dnMySQL then AColumn.TypeName := 'INT'
      else                               AColumn.TypeName := 'INTEGER';
    end;
    ftLargeint:      AColumn.TypeName := 'NUMERIC(%l)';
    ftString:        AColumn.TypeName := 'VARCHAR(%l)';
    ftWideString:    AColumn.TypeName := 'NVARCHAR(%l)';
    ftFixedChar:     AColumn.TypeName := 'CHAR(%l)';
    ftFixedWideChar: AColumn.TypeName := 'NCHAR(%l)';
    ftDate:          AColumn.TypeName := 'DATE';
    ftTime:          AColumn.TypeName := 'TIME';
    ftDateTime:      AColumn.TypeName := 'DATETIME';
    ftTimeStamp:     AColumn.TypeName := 'TIMESTAMP';
    ftFloat:
    begin
      if      FDriverName = dnMSSQL      then AColumn.TypeName := 'FLOAT'
      else if FDriverName = dnMySQL      then AColumn.TypeName := 'FLOAT'
      else if FDriverName = dnPostgreSQL then AColumn.TypeName := 'NUMERIC(%p,%s)'
      else                                    AColumn.TypeName := 'DECIMAL(%p,%s)';
    end;
    ftSingle:        AColumn.TypeName := 'REAL';
    ftExtended:
    begin
      if      FDriverName = dnMSSQL then AColumn.TypeName := 'DOUBLE'
      else if FDriverName = dnMySQL then AColumn.TypeName := 'DOUBLE'
      else                               AColumn.TypeName := 'DOUBLE PRECISION';
    end;
    ftCurrency:
    begin
      if      FDriverName = dnMSSQL      then AColumn.TypeName := 'MONEY'
      else if FDriverName = dnMySQL      then AColumn.TypeName := 'DECIMAL(%p,%s)'
      else                                    AColumn.TypeName := 'NUMERIC(%p,%s)';
    end;
    ftBCD, ftFMTBcd:
    begin
      if      FDriverName = dnPostgreSQL then AColumn.TypeName := 'MONEY'
      else if FDriverName = dnMSSQL      then AColumn.TypeName := 'MONEY'
      else                                    AColumn.TypeName := 'DECIMAL(%p,%s)';
    end;
    ftMemo:
    begin
      if FDriverName = dnFirebird then AColumn.TypeName := 'BLOB SUB_TYPE TEXT'
      else                             AColumn.TypeName := 'LOGBLOB';
    end;
    ftWideMemo, ftBlob:
    begin
      if FDriverName = dnFirebird then AColumn.TypeName := 'BLOB SUB_TYPE TEXT'
      else                             AColumn.TypeName := 'TEXT';
    end;
  else
    raise Exception.Create('Tipo da coluna definida, não existe no ORMBr.');
  end;
end;
Dependendo do tipo definido na propriedade da sua classe modelo, o ORMBr irá identificar o tipo do campos no seu banco de dados, exemplo, se definirmos a propriedade do tipo ftWideMemo ou ftBlob, o ORMBr irá identificar que no seu banco dados a coluna é BLOB SUB_TYPE TEXT no caso o banco seja Firebird caso contrário irá identificar como TEXT para os demais bancos. 
Vemos aqui que o tipo definido no ORMBr, poderá se comportar diferente dependendo do banco usado, então pessoal atenção a esse código, qualquer situação adversa me comunique, pois acredito que não pensei em todas as situações e tipos.

ORMBr - Ao Usar, Perdemos em Performance?


Muitos pensam que usar o ORMBr perderia performance, gente o ORMBr trabalho com duas linhas de frente para vocês.
1a ) Ele fará de forma SUPER simples TUDO o que você teria que fazer manual, como SELECT, Adicionar TFields e configurar um a um, gerenciar abertura de subtabelas em mestre-detalhe, TUDO isso passa a ser automatizado.
2a) Ele fará de forma SURPER simples tudo o que os componentes DataSet já faz, pois o que você achar que um TFDQuery faz, quando você alimenta os TFields dele, em seguida dispara um Post e um ApplyUpdate?

Simplesmente montam o comando SQL internamente e mandam para o banco, é exatamente o que o ORMBr faz também.

Se é assim que funciona, como podemos perder performance ?

ORMBr - TFields em Runtime

Em 2006 palestrei na Borcon e minha palestra foi sobre Multicamadas com Multibancos, na época só conseguia aplicar multibancos através de uma técnica criada por mim, que foi a criação de TFields em runtime. A Criação de TFields em Designer além de ser um CAUS para manutenções futuras em projetos, me trazia um problema de incompatibilidade entre os tipos de TFields que o Delphi criava para bancos diferentes, exemplo o tipo data, e té hoje isso acontece, só com a aquisição do FireDAC passou a ter um recurso nativo de mapeamento de tipos para os TFields, criados em designer, recurso esse que tem a mesma finalidade da que criei a mais de 10 anos atrás, resolver incompatibilidade de tipos em bancos diferentes. Porém a técnica usada por mim, elimina ainda outras situações como a manutenções futuras no projeto, mas que manutenções são essas que você diz Isaque? Se criar um campo no banco VARCHAR(10) em designer será criado um TField do tipo TStringField de size 10, esse TField pode ter sido adicionados em vários pontos do meu projeto, tela de cadastro, consultas etc..., se algum dia eu precisar mudar o tamanho desse campo no banco para 15, terá que lembrar todos os pontos do meu sistema que adicionou o TField para esse campo, caso contrário, mesmo no banco ele tendo tamanho 15, o delphi irá limitar a digitação em 10, esse é um dos exemplos simples, existem outras. Com a técnica de criar TFields em runtime, esse problema é TOTALMENTE resolvido, pois o TField será criado com base no campo atual do banco, sendo criado sempre de forma atual. Com o nascimento do ORMBr, isso ficou bem mais simples, pois além das grandes vantagens em agilidade que o ORMBr traz, ele trata, cria e configura cada TField em runtime, isso tudo com base no modelo, vejamos como podemos definir isso no modelo do ORMBr:
[Column('price', ftFloat, 18, 3)]
[Dictionary('Preço Unitário','Mensagem de validação','0','#,###,##0.00','',
taRightJustify)]
property price: Double Index 4 read Fprice write Fprice;
Vejamos os atributos:
Column : Informo o nome do campo, o tipo que quero e tamanho, pronto o ORMBr faz o resto
Dictionary : Informo o DisplayLabel, Mensagem de validação, Valor Default, DisplayFormat, EditMask, e o alinhamento.

terça-feira, 8 de novembro de 2016

Técnica Para Ajudar no Dia Dia

Seja bem vindo a mais esse artigo, e boa leitura. 
Desenvolvedores, vive seu dia dia escrevendo código, mas claro o foco sempre na lógica e na melhor forma de fazer, e na maioria das vezes tem que recorrer a uma ajudinha, seja ela no help da linguagem ou no Google, para lembrar da sintaxe correta de um comando, procedure ou função. O sábio não é aquele que sabe e faz tudo, mas aquele que lembra que existe, e tem a coragem de procurar, e se não existe, a coragem de estudar para conseguir aprender e fazer. 
Existem situações das quais ao escrever um código, nos deparamos com a dúvida e o esquecimento de até mesmo o que nós criamos, exemplo o nome de uma coluna no banco de dados, e é nessa situação que vou passar uma dica de um possível recurso para ajudar no seu dia dia.
Em um ponto do código, precisa escrever um comando SQL, do qual vai selecionar varias colunas de uma determinada tabela do banco de dados, então faz:
'SELECT TableName.Codigo, TableName.Nome, TableName.Endereco FROM TableName'
Simples, mas nem toda vez irá lembrar de todos os nomes e de todas as tabelas do banco de dados, dai tende a parar, e ir olhar no banco qual o nome correto para a determinada coluna, e quando esse banco for dados manutenção por mais de uma pessoa, só tende piorando. 
Você já pensou em uma técnica para te ajudar no dia dia nesse caso? Não, então vou te dar uma dica, segue abaixo:
...
Type
  TMyTable = class
  private
    class function GetTableName: string;
    class function GetCodigo: string;
    class function GetNome: string;
    class function GetEndereco: string;
  public
    class property TableName: string read GetTableName;
    class property Codigo: string read GetCodigo;
    class property Nome: string read GetNome;
    class property Endereco: string read GetEndereco;
  end;

implementation

class function TMyTable.GetTableName: string;
begin
  Result := 'TableName';
end;  

class function TMyTable.GetCodigo: string;
begin
  Result := 'TableName.Codigo';
end;  

class function TMyTable.GetNome: string;
begin
  Result := 'TableName.Nome';
end;  

class function TMyTable.GetEndereco: string;
begin
  Result := 'TableName.Endereco';
end;  

end.

Usando a class: 'SELECT ' + TMyTable.Codigo + ',' +
                            TMyTable.Nome + ',' +
                            TMyTable.Endereco + 
                ' FROM ' + TMyTable.TableName;
Qual a vantagem? como criamos a class, nela estará todas as propriedades com os nomes dos campos da tabela, então ao precisarmos podemos pedir a ajuda do Delphi ao recurso "Code Completion" e ele mostrará todos os possíveis nomes existentes na class, facilitando assim nossa busca.

quarta-feira, 2 de novembro de 2016

ORMBr - Gerenciamento DB (Interbase e PostgreSQL)

Seja bem vindo a mais esse artigo, e boa leitura. 
Lancei hoje os drivers para gerenciamento de banco de dados para Interbase e PostgreSQL, já estão disponíveis no repositório, dúvidas, perguntas, bugs, sugestões, gentileza podem ser postados no Fórum http://www.ormbr.com.br/forum e os fontes podem ser baixados no site http://www.ormbr.com.br no menu Download. 
Quero aqui deixar meus agradecimentos ao Juliomar Marchetti, mais informações sobre ele podes ser encontradas no seu blog http://www.juliomarmarchetti.com.br, ele foi quem teve a ideia e colocou mão na massa para aproximar os interessados no projeto ORMBr ao seu autor, ele criou um Canal e um Grupo no Telegram o link para o Canal https://telegram.me/canalormbr e para o Grupo https://telegram.me/ormbr, convido a todos interessados a participar. 
O ORMBr já da suporta a gerenciamento a banco de dados com base no modelo criado, até o momento já temos os drivers para os bancos: MSSQL, MySQL, Firebird, Interbase, SQLite e PostgreSQL, o recurso oferecido até o momento são criação de tabelas com sua estrutura completa e com todos os recursos de coluna como TIPOS, NOT NULL, DEFAULT, juntamente com recursos como criação de PrimaryKey, ForeignKey, Indexe e Check, isso funcional e testado, e não acabou por ai, tem ainda o recurso de ADD COLUMN nova a estrutura, caso a coluna seja adicionado ao modelo e ser rodado o recurso de verificação de metadata, segue abaixo um exemplo de como usar o recurso:
procedure TForm1.Button1Click(Sender: TObject);
var
  oManager: TDatabaseAbstract;
  oConnection: IDBConnection;
begin
  // Instância da class de conexão via FireDAC, segundo parametro
  // o Driver de qual Banco usado
  oConnection := TFactoryFireDAC.Create(FDConnection1, dnPostgreSQL);

  oManager := TDatabaseManager.Create(oConnection);
  oManager.BuildDatabase;

  for cDDL in oManager.GetCommandList do
      Memo1.Lines.Add(cDDL.Command);

  oManager.Free;
end;
Nota: Até o momento a criação do banco de dados, tem que ser feito manualmente, estou estudando a implementação desse recurso via ORMBr, após a criação do banco vazio, só configura-lo ao engine de conexão que no ORMBr podem ser: FireDAC, DBExpress ou Zeos até agora, em seguida criar a fabrica de conexão conforme engine de preferência e rodas a atualização conforme modelo criado. Abaixo um exemplo de um modelo bem completo para estudo e teste:
unit ormbr.model.person;

interface

uses
  Classes,
  DB,
  /// orm
  ormbr.mapping.attributes,
  ormbr.types.mapping,
  ormbr.mapping.register;

type
  [Entity]
  [Table('Person','Tabela de pessoas')]
  [PrimaryKey('Id', NoSort, False, 'Chave primária')]
  [Indexe('IDX_FirstName','FirstName', NoSort, True, 'Indexe por nome')]
  [Check('CHK_Age', 'Age >= 0')]
  TPerson = class
  private
    { Private declarations }
    FId: Integer;
    FFirstName: string;
    FLastName: string;
    FAge: Integer;
    FSalary: Double;
  public
    { Public declarations }
    [Restrictions([NoUpdate, NotNull])]
    [Column('Id', ftInteger)]
    [Dictionary('Código ID','Mensagem de validação','0','','',taCenter)]
    property Id: Integer Index 0 read FId write FId;

    [Restrictions([NotNull])]
    [Column('FirstName', ftString, 40)]
    [Dictionary('Primeiro nome','Mensagem de validação','','','',taLeftJustify)]
    property FirstName: String Index 1 read FFirstName write FFirstName;

    [Column('LastName', ftString, 30)]
    [Dictionary('Último nome','Mensagem de validação','','','',taLeftJustify)]
    property LastName: String Index 2 read FLastName write FLastName;

    [Restrictions([NotNull])]
    [Column('Age', ftInteger)]
    [Dictionary('Idade','Mensagem de validação','0','','',taCenter)]
    property Age: Integer Index 3 read FAge write FAge;

    [Restrictions([NotNull])]
    [Column('Salary', ftCurrency, 18, 3)]
    [Dictionary('Preço','Mensagem de validação','0','','',taRightJustify)]
    property Salary: Double Index 4 read FSalary write FSalary;
  end;

implementation

initialization
  TRegisterClass.RegisterEntity(TPerson);

end.

Total de visualizações

Postagem em destaque

ORMBr - Mapeamento objeto-relacional

Mapeamento objeto-relacional ( ou ORM, do inglês: Object-relational mapping ) é uma técnica de desenvolvimento utilizada para reduzir...

Todo os direitos reservados.. Tecnologia do Blogger.

Seguidores