Fim? – Que tal um ORM Básico? Parte 14

Olá Pessoal

Depois de um longo tempo de inatividade, estou de volta. Devido a total falta de tempo, não voltarei a postar com a mesma frequência com que vinha postando antes. Irei também, finalizar esta série. A partir de agora, sempre que eu fizer alguma atualização e que esta seja significativa, informo o que foi feito.

Coloquei os fontes no Google Code. Para baixá-los, acesse: code.google.com/p/blog-luiz-orm/

Alguns leitores do blog se mostraram interessados em contribuir com o projeto. Achei interessante a ideia. Portanto, quem desejar, sinta-se à vontade. Toda ajuda será bem vinda!

Nos últimos dias, voltei a atualizar os fontes, pois estou utilizando-o em um sistema de controle de estoque.  Abaixo, falo um pouco sobre as alterações mais importantes.

Alguns Ajustes

Renomeei as units para prsBase, prsAtributos, prsDaoIBX.

Separando Responsabilidades

Nossas classes DAO estavam sobrecarregadas, com muitas responsabilidades. Fugimos um pouco das boas práticas (sem querer querendo viu?!). Por exemplo: TDaoIBX, além do próprio DAO ainda tinha que lhe dar com a Conexão e com a Transação. Agora, retirei dela esta alçada e criei novas classes na unit prsDaoIBX:

 TTransacaoIbx = class(TTransacaoBase)
  private
    // transação para crud
    FTransaction: TIbTransaction;

  public
    constructor Create(ABanco: TIBDatabase);
    destructor Destroy; override;

    function InTransaction: Boolean; override;
    procedure Snapshot;
    procedure Read_Commited;
    procedure StartTransaction; override;
    procedure Commit; override;
    procedure RollBack; override;

    property Transaction: TIbTransaction read FTransaction write FTransaction;
  end;

  TConexaoIbx = class(TConexaoBase)
  private
    // conexao com o banco de dados
    FDatabase: TIBDatabase;
    // transação para consultas
    FTransQuery: TIbTransaction;
  public
    constructor Create();
    destructor Destroy; override;

    function Conectado: Boolean; override;

    procedure Conecta; override;

    property Database: TIBDatabase read FDatabase write FDatabase;
    property TransQuery: TIbTransaction read FTransQuery write FTransQuery;
  end;

Vamos à classe TDaoIBX

Nossa classe Dao para IBX sofreu alguns ajustes importantes:

TDaoIbx = class(TDaoBase)
  private
    FConexao: TConexaoIbx;
    // query para execução dos comandos crud
    Qry: TIBQuery;

    Function DbToTabela<T: TTabela>(ATabela: TTabela; ADataSet: TDataSet):
      TObjectList<T>;
  protected
    // métodos responsáveis por setar os parâmetros
    procedure QryParamInteger(ARecParams: TRecParams); override;
    procedure QryParamString(ARecParams: TRecParams); override;
    procedure QryParamDate(ARecParams: TRecParams); override;
    procedure QryParamCurrency(ARecParams: TRecParams); override;
    procedure QryParamVariant(ARecParams: TRecParams); override;

    // métodos para setar os variados tipos de campos
    procedure SetaCamposInteger(ARecParams: TRecParams); override;
    procedure SetaCamposString(ARecParams: TRecParams); override;
    procedure SetaCamposDate(ARecParams: TRecParams); override;
    procedure SetaCamposCurrency(ARecParams: TRecParams); override;

    function ExecutaQuery: Integer; override;
  public
    constructor Create(AConexao: TConexaoIbx; ATransacao: TTransacaoIbx);
    destructor Destroy; override;

    // dataset para as consultas
    function ConsultaSql(ASql: string): TDataSet; override;
    function ConsultaTab(ATabela: TTabela; ACampos: array of string): TDataSet; override;
    function ConsultaGen<T: TTabela>(ATabela: TTabela; ACampos: array of string): TObjectList<T>;

    // pega campo autoincremento
    function GetID(ATabela: TTabela; ACampo: string): Integer; override;

    // recordcount
    function GetRecordCount(ATabela: TTabela; ACampos: array of string): Integer; override;

    // crud
    function Inserir(ATabela: TTabela): Integer; override;
    function Salvar(ATabela: TTabela): Integer; override;
    function Excluir(ATabela: TTabela): Integer; override;
    function Buscar(ATabela: TTabela): Integer; override;
  end;

Destaque para:

  • Linha 3 – FConexao do tipo TConexaoIbx – onde definimos qual conexão iremos utilizar
  • Linha 34 – Função de consulta que devolve uma lista de objetos genérica
  • Linha 38 – Renomeei o método de auto incremento para GetID e agora passamos um objeto e não mais uma string
  • Linha 42 – Método para pegar a contagem de registros em determinada tabela

Novos Atributos

A unit prsAtributos também sofreu alguns ajustes e novas implementações:


   /// <summary>
  /// Atributos de Chave Primaria e Relacionamentos
  /// </summary>

  AttPK = class(TCustomAttribute)
  end;

  /// <summary>
  /// Atributos de Validação
  /// </summary>

  AttBaseValidacao = class(TCustomAttribute)
  private
    FMensagemErro: string;
    procedure SetMessagemErro(const Value: string);
  public
    property MessagemErro: string read FMensagemErro write SetMessagemErro;
  end;

  AttNotNull = class(AttBaseValidacao)
  public
    constructor Create(const ANomeCampo: string);
    function ValidarString(Value: string): Boolean;
    function ValidarInteger(Value: Integer): Boolean;
    function ValidarFloat(Value: Double): Boolean;
    function ValidarData(Value: Double): Boolean;
  end;

  AttMinValue = class(AttBaseValidacao)
  private
    FValorMinimo: Double;
  public
    constructor Create(ValorMinimo: Double; const ANomeCampo: string);
    function Validar(Value: Double): Boolean;
  end;

  AttMaxValue = class(AttBaseValidacao)
  private
    FValorMaximo: Double;
  public
    constructor Create(ValorMaximo: Double; const ANomeCampo: string);
    function Validar(Value: Double): Boolean;
  end;

Como pode ser visto, quando comparamos com o último fonte disponibilizado aqui no blog, houve uma mudança radical e será necessário rever as classes relativas às tabelas do banco de dados. Abaixo, um exemplo de como devemos criar nossas classes:

uses PrsBase, PrsAtributos, Cidade;

type
  [AttTabela('Cliente')]
  TCliente = class(TTabela)
  private
    FID: Integer;
    FNOME: string;
    FCIDADEID: Integer;
    procedure SetID(const Value: Integer);
    procedure SetNOME(const Value: string);
    procedure SetCIDADEID(const Value: Integer);
  public
    [AttPk]
    [AttNotNull('Código do cliente')]
    property ID : Integer read FID write SetID;
    [AttNotNull('Nome do Cliente')]
    property NOME : string read FNOME write SetNOME;
    [AttNotNull('Código da Cidade')]
    property CIDADEID: Integer read FCIDADEID write SetCIDADEID;
  end;

O trecho acima refere-se a unit Clientes que está nos fontes.

Eu ainda não estou satisfeito com relação ao atributo que verifica se o campo está vazio (AttNotNull). Isso significa que em breve poderemos ter novas alterações nesta unit.

Como podem observar, atualizei apenas o Dao do IBX. Isso porque atualmente estou com problemas com o UIB, depois que passei para meu novo computador. Por isso, os fontes também estão sem esta unit.

Pensei em fazer um vídeo demonstrando e testando tudo o que foi feito até aqui, mas encontrei dificuldade para achar um programa que me permitisse gravar, assim como Camtasia faz, mas que fosse free (Claro!). Se tiverem um pra me indicar, postem nos comentários.

É isso! Espero que gostem deste post. Abraços e até mais!

Sobre o autor: Luiz Carlos (60 Posts)

Desenvolvedor de software Balsas/MA


Compartilhe:

11 Replies to “Fim? – Que tal um ORM Básico? Parte 14”

  1. Grande, Luiz os seus post são excelentes.

    Como já havia dito em outro post, eu fiz o DAO para uso com o FireDac e implementei os campos BLOB,
    percebi que mesmo nesta ultima atualização vc não implementou os campos BLOB, poderia me dizer se é por estratégia ou vc não faz uso deles, e por ultimo se vc quiser eu envio o DAO com FireDac embora necessite ainda de melhorias já que o FireDac se conecta com os principais SGDB’s e eu fixei a conexão com o FIREBIRD.

      1. Já te enviei uma solicitação Obrigado.
        Você já tentou usar nesse post uma tabela com campo auto-incremento ? se sim poderia me dizer como fez ou como fazer ? Obrigado.

  2. Luiz, quero primeiramente lhe parabenizar pelo artigo, super didático, objetivo e bastante útil… estou implementando (creio que o colega Jonathan também já fez) com o FireDac e gostaria de contribuir com o projeto, vi que o código se encontra no GoogleCode porém, seria interessante organizar o que se deve ser implementado (requisitos e/ou melhorias), aguardo retorno… abraços

    1. Olá Gustavo

      Estou pensando passar a usar o git/github. Lá podemos criar as histórias, os participantes, brunchs, etc…

      Só me dá um tempinho… e já aproveito para pedir desculpas… aqui, a água já está acima do nariz (aka tempo esgotado!). ;)

  3. Boa tarde, você cita que renomeou o método de auto incremente para GetID. Só que não encontrei nada sobre como era o método antes e sobre o GetID eu só encontrei a assinatura. Poderia disponibilizar este método completo?

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *