sexta-feira, 14 de abril de 2017

Cadastro Cliente Servidor Parte I

Neste Exemplo vamos abordar Rotinas de Inserção, Alteração e exclusão num ambiente
Cliente servidor onde os comandos são executados diretamente no servidor.

Utilizei o DelphiXE5 mas pode ser feito a partir da versão do Delphi que trouxe a tecnologia FIREDAC,  Firebird 2.5, e a IDE para Firebird IbExpert personal  edition, é gratuito só precisa fazer um cadastro e de mês em mês ele pede uma nova senha que você recebe no seu e-mail, é muito bom. 

Baixe em ibexpert.com, se não quiser, utilize o da sua preferência.
Neste exemplo não utilizaremos o componente TTable, Tdbedit, e nada que ligue diretamente a campos de tabelas.

Vou mostrar como fazer isso de forma simples e seguro.

Iniciaremos Criando uma tabela no seu BD conforme abaixo:

Tabela: tb_agenda

create table tb_agenda(
age_id       integer not null primary key,
age_nome     varchar(50),
age_telefone varchar(10),
age_email    varchar(50),
age_ativo    integer)


Altere vamos transformar o campo age_id como autoincremento.


Clique com o botão direito do mouse em cima da tabela tb_agenda, em seguida em Edit Table.

Dê um duplo clique no campo AGE_ID e surgirá a janela abaixo:

Em seguida clique na aba AutoIncrement e marque a caixa Create Generator.

Depois disso clique em OK, na próxima janela em Commit.

Agora veja no Database Explorer



Agora nós temos uma tabela com campo inteiro e autoincremento.
Agora Vamos Criar uma VIEW que são os dados que serão apresentados nas pesquisas e no dbgrid, não vamos ligar diretamente a tabela tb_agenda.

Se preferir pode criar diretamente o generator assim:

create generator gen_tb_agenda_id ou outro nome de sua preferência mas cuidado, mais adiante utilizaremos este nome.





View: vi_agenda
create view vi_agenda(
 
id       ,
nome     ,
telefone ,
email    ,
ativo    )
as select
age_id       ,
age_nome     ,
age_telefone ,
age_email    ,
age_ativo
from tb_agenda

Agora vamos criar um procedure para manipular os dados e as rotinas de Inserir, Alterar e Excluir Registros:
CREATE PROCEDURE SP_AGENDA (
    id integer,
    nome varchar(50),
    telefone varchar(10),
    email varchar(50),
    ativo integer,
    oper integer)
as
declare variable reg integer;
begin
  if (oper=1) then
  begin
    select gen_id(gen_tb_agenda_id, 1) from rdb$database into :reg;
    insert into tb_agenda (age_id, age_nome, age_telefone, age_email, age_ativo)
    values (:reg, :nome, :telefone, :email, :ativo);
  end
  if (oper=2) then
  begin
    update tb_agenda set
    age_nome    =:nome,
    age_telefone=:telefone,
    age_email   =:email,
    age_ativo   =:ativo
    where age_id=:id;
  end
  if (oper=3) then
  begin
    delete from tb_agenda
    where age_id=:id;
  end
end

Agora vamos para o Delphi.

Crie um novo projeto e salve de acordo com a sua conveniência. Vamos inserir os componentes necessários:

Componente
Propriedade Name
Propriedade MaxLength
Propriedade Caption
Form
Form1 (pode mudar)

Agenda
Edit
Nome
50

Edit
Telefone
10

Edit
Email
50

Button
btIncluir

Novo
Button
btAlterar

Alterar
Button
btExcluir

Excluir
Button
btSalvar

Salvar
DataSource
dsAgenda


DbGrid
dbgAgenda


DbNavigator
DbNavigator1


CheckBox
Ativo



Observe que os edit´s foram nomeados de acordo com os nomes/apelidos que foram atribuídos a view que criamos.

Veja abaixo como ficou o LayOut do fPrincipal é bem básico, somente para fins didático, determine sua própria forma de layout.



Agora Vamos criar o nosso DataModule utilizando o menu File/New/Other e em Delphi Files clique em Data Module em seguida em OK.
Altere a Proprieda Name para Dm, e salve como uDm.
Vamos utiizar os componentes FireDac para acesso e manipulação de dados.
Adicione:
Da Paleta FireDac: 1 FDConnection,  1 FDTransaction, 1 FDQuery, 1 FDStoredProc.
Da Paleta FireDacLinks: 1 FDPhysFBDriverLink.
Da Paleta FireDac UI: 1 FDGUIxWaitCursor.

Vamos setar as propriedades do nosso  FDConnection1 dando um duplo clique no componente surgirá a janela abaixo:



Altere a propriedade  LoginPrompt do componente FDConnection1  para False.

Altere a propriedade name da FDQuery1 para qAgenda, e verifique a propriedade connection set está setado para o nosso FDConnection1.
Na propriedade SQL digite: SELECT * FROM VI_AGENDA
Altere a Propriedade Name do FDStoredProc1 para spAgenda, este componente será ligado a SP_agenda,   StoredProcName para a Procedure que criamos no FireBird SP_AGENDA, veja abaixo:


Veja agora como ficou nosso datamodule:

No form principal:
-Tecle Alt+F11 para adicionar o datamodlule à cláusula Uses.
-Adicione uma variável global no form conforme abaixo:
var
  Form1: TForm1; //já existente
  oper:Integer;

Ligue a propriedade dataset do dsAgenda para qAgenda:


Ligando o DataSouce à qAgenda

Ligue a propriedade datasource do Dbgrid com dsAgenda.

Agora vamos criar alguma procedures e function que serão utilizados mais adiante

Vamos ao datamodule:

Veja a declaração:
  private
    { Private declarations }
  public
    { Public declarations }
  end;

//declare as procedure antes da cláusula var do Datamodule para que seja utilizado em todo o //sistema.

  //Procedure que mostra os dados nos edit´s
  procedure Banco_Tela( SP:TDataSet; Form:TForm );
  //Procedure que Trava ou Lira os campos para digitação
  procedure Trava_Campo( Form:TForm; Status:Boolean );
  function IIF(Expressao: Boolean; Result_True, Result_False: Variant): Variant;
  //Limpar os campos
  procedure Limpa_Campo( Form:TForm );

As Procedures:

procedure Banco_Tela( SP:TDataSet; Form:TForm );
var
  i: Integer;
  Source: TComponent;
begin
  for i := 0 to SP.FieldDefs.Count-1 do
    begin
      Source := Form.FindComponent(SP.FieldDefs.Items[i].Name);
      if Source <> nil then
         begin
          if Source is TEdit then
            TEdit(Source).Text := SP.FieldByName( SP.FieldDefs.Items[i].Name ).AsString ;
          if Source is TMaskEdit then
            TMaskEdit(Source).Text := SP.FieldByName( SP.FieldDefs.Items[i].Name ).AsString ;
          if Source is TComboBox then begin
            if SP.FieldByName( SP.FieldDefs.Items[i].Name ).DataType=ftInteger then begin
              TComboBox(Source).ItemIndex := SP.FieldByName( SP.FieldDefs.Items[i].Name ).AsInteger;
            end else begin
              TComboBox(Source).Text := SP.FieldByName( SP.FieldDefs.Items[i].Name ).AsString;
            end;
          end;
          if Source is TCheckBox then begin
            if SP.FieldByName( SP.FieldDefs.Items[i].Name ).DataType=ftInteger then begin
              TCheckBox(Source).Checked := SP.FieldByName( SP.FieldDefs.Items[i].Name ).AsInteger=0;
            end else begin
              TCheckBox(Source).Checked := False;
            end;
          end;
        end;
    end;
end;


procedure Trava_Campo( Form:TForm; Status:Boolean );
var
  i : integer;
  Source: TComponent;
begin
  for i := 0 to Form.ComponentCount-1 do
    begin
      Source := Form.Components[i];
      if Source <> nil then
        begin
          if Source is TEdit       then TEdit(Source).Enabled       := Status;
          if Source is TMaskEdit   then TMaskEdit(Source).Enabled   := Status;
          if Source is TComboBox   then TComboBox(Source).Enabled   := Status;
          if Source is TCheckBox   then TCheckBox(Source).Enabled   := Status;
        end;
    end;
end;

function IIF(Expressao: Boolean; Result_True, Result_False: Variant): Variant;
begin
  if Expressao then
    Result := Result_True else Result := Result_False;
end;

procedure Limpa_Campo( Form:TForm );
var
  i : integer;
  Source: TComponent;
begin
  for i := 0 to Form.ComponentCount-1 do
    begin
      Source := Form.Components[i];
      if Source <> nil then
        begin
          if Source is TEdit       then TEdit(Source).Clear;
          if Source is TMaskEdit   then TMaskEdit(Source).Clear;
          if Source is TComboBox   then TComboBox(Source).ItemIndex := 0;
          if Source is TCheckBox   then TCheckBox(Source).Checked:=False;
        end;
    end;
end;


No Evento OnShow do Form digite:
   Dm.qAgenda.Open();
   Oper:=0; //Iniciar sem comando
   if Dm.qAgenda.RecordCount>0 then begin
     Dm.qAgenda.Last;
     Banco_Tela(Dm.qAgenda, Form1);
   end;
   Trava_Campo(Form1, False);


No Evento OnClose do Form Digite:
 Dm.qAgenda.Close;

 
Veja em execução o nosso form.


Vamos implementar o Evento OnClick do btNovo.

procedure TForm1.NovoClick(Sender: TObject);
begin
   Oper:=1; //Inserir
   Trava_Campo(Form1, True); //Libera os campos para digitação
   Limpa_Campo(Form1); //Limpa os campos
   Nome.SetFocus; //Direciona o foco para o edit chamado Nome
end;

Após a digitação, o usuário clicará em Salvar, vamos implementar o evento do btSalvar:

procedure TForm1.btSalvarClick(Sender: TObject);
begin
  try
    Dm.FDTransaction1.StartTransaction;
    with Dm.spAgenda do Begin
      if Not Prepared then prepare;
      //Se for uma inclusão, não vamos passar o id que será gerado automaticamente com o    
      //gen_tb_agenda_id
      if Oper>1 then //Alteração ou exclusão
        ParamByName('id').AsInteger   := Dm.qAgenda.FieldByName('id').AsInteger
      Else //Inclusão, parâmetro com valor zero só pra não dar excessão na execução da procedure
        ParamByName('id').AsInteger   := 0;
      ParamByName('nome').AsString    := nome.Text;
      ParamByName('telefone').AsString:= Telefone.Text;
      ParamByName('email').AsString   := email.Text;
       //Se tiver Marcado esta inativo então ele grava 0=ativo, 1=Inativo;
      ParamByName('ativo').AsInteger  := iif(Ativo.Checked, 0, 1);
      ParamByName('oper').AsInteger   := oper; //Variavel de controle de inserção, etc
      ExecProc;
    End;
    Dm.FDTransaction1.Commit;
    Dm.qAgenda.Refresh;
  except
    Dm.FDTransaction1.Rollback;
    raise;
  end;
  Oper:=2; //Iniciar como alterar
  Dm.qAgenda.Last;
  Banco_Tela(Dm.qAgenda, Form1);
  Trava_Campo(Form1, False);
end;

Observe que acima utilizei “Dm.qAgenda.FieldByName('id').AsInteger”, existe uma discussão nos fóruns de Delphi que: qual seria a forma que menos consome recurso do servidor ou maquina local, se “Dm.qAgenda.FieldByName('id').AsInteger” , “Dm.qAgendaId.AsInteger” ou
Dm.qAgenda.fields[x].AsInteger, mas isso você pode utilizar a forma mais conveniente.


Evento do btAlterar:

procedure TForm1.AlterarClick(Sender: TObject);
begin
   Oper:=2; //Alterar
   Trava_Campo(Form1, True); //Libera os campos para digitação
   Banco_Tela(Dm.qAgenda, Form1);
   Nome.SetFocus; //Direciona o foco para o edit  “Nome”
end;

Evento btExcluir:
procedure TForm1.ExcluirClick(Sender: TObject);
Begin
  //Aqui você pode gerar uma pergunta antes de excluir
   Oper:=3; //Excluir
   Banco_Tela(Dm.qAgenda, Form1);
   btSalvar.OnClick(Sender);
end;

No evento OnDataChange do dsAgenda coloque:
  Banco_Tela(Dm.qAgenda, Form1);



Em execução:



Pra finalizar, esta forma de utilização de controle de dados que chamam cliente/servidor onde o processo é feito no servidor, liberam os recursos da estação.
Desta forma, pode ser feitos os filtros, seleções, junção de tabelas para relatórios tudo vai depender de como você fez a modelagem.

A utilização de View, este recurso permite que se crie visualizações bem complexas utilizado várias tabelas ao mesmo tempo, mas este assunto será abordado em um post específico.

Se gostou comente, dúvidas, sugestões também.

No próximo post faremos as rotinas de Pesquisas.
E a quem interessar faremos um cadastro em SQLServer 2008.

Até o próximo post.

Nenhum comentário:

Postar um comentário