Chegar a um CRUD é um grande desafio. Associar um MVC no desenvolvimento e a utilização de RESTful para persistir os dados (com OData) só faz crescer o desafio.
O desafio vem do fato de tudo ser novidade e forçar a quebrar paradigmas antes impensáveis utilizando a ferramenta do dia-a-dia, o Delphi.
Vamos ligar os componentes:
TIdHTTPRestClient é responsável em fazer a
comunicação entre o cliente e o servidor RESTful.
É o canal para buscar dados no servidor, bem como enviar dados para o servidor (é um componente de transporte).
Os preenchimento das propriedades do RestClient pode ser feito manualmente, ou ainda, de forma automática se for utilizado em conjunto com um TODataBuilder.
Com o TODataBuilder permite construir a soliciatação GET a ser enviada ao servidor OData.
Ligar ao TODataBuilder a propriedade RestClient com o TIdHTTPRestClient. Com isto o comando construído no Builder será repassado (preenchido automático) no RestClient. ver mais….
O passo seguinte é ligar o TODataDatasetAdpater.
O Adapter recebe os dados do RestClient e liga com o Dataset.
Ligar o Builder, Dataset e o ResponseJSON( RestClient).
Para obter os dados com os servidor, chamar o método execute. ver mais…
Feito estas ligações nos componentes, já é possível chamar o EXECUTE do Adapter que irá preencher o Dataset com a resposta do servidor.
Para enviar um INSERT, DELETE ou UPDATE para o servidor ( ver exemplo).
O código a seguir mostra como montar os dados a serem enviado para o servidor persistir as alterações.
Os seguintes métodos do Adapter são importantes, como no exemplo:
ODataDatasetAdapter1.AddRowSet(rctInserted, DataSet); /// põe na pilha um INSERT; ODataDatasetAdapter1.AddRowSet(rctModified, DataSet); /// põe na pilha um UPDATE ODataDatasetAdapter1.AddRowSet(rctDeleted, DataSet); /// põe na pilha um DELETE; ODataDatasetAdapter1.ApplyUpdates(nil, rmPATCH); /// atualiza o servidor com os dados da pilha; ODataDatasetAdapter1.Execute; /// faz um SELECT no banco de dados ODataDatasetAdapter1.ClearChanges; /// limpa a pilha
Código de exemplo que esta no projeto MVCBr. no git
[code lang=”pascal”]
{ //************************************************************// }
{ // // }
{ // Código gerado pelo assistente // }
{ // // }
{ // Projeto MVCBr // }
{ // tireideletra.com.br / amarildo lacerda // }
{ //************************************************************// }
{ // Data: 10/03/2017 21:21:54 // }
{ //************************************************************// }
///
/// Uma View representa a camada de apresentação ao usuário
/// deve esta associado a um controller onde ocorrerá
/// a troca de informações e comunicação com os Models
….
DBGrid1: TDBGrid;
DataSource1: TDataSource;
/// Componente de Envio de mensagem HTTP para o servidor OData RESTful
IdHTTPRestClient1: TIdHTTPRestClient;
/// Construção de URL a ser enviado ao servidor
ODataBuilder1: TODataBuilder;
/// Desempacota a resposta do servidor e preenche o Dataset
ODataDatasetAdapter1: TODataDatasetAdapter;
/// Dataset que recebe a resposta do servidor – preenchida com o Adpater
FDMemTable1: TFDMemTable; /// FireDAC
Button1: TButton; /// botão GET
Button2: TButton; /// botão ApplayUpdates
….
private
FLoading: boolean; /// Flag para marcar se esta fazendo carga inicial da tabela.
FState: TDataSetState; /// Guarda o STATE do Dataset a ser usando no AfterPost
protected
public
{ Public declarations }
…
end;
Implementation
{$R *.DFM}
…..
/// No evento AfterPost do Dataset, armazena na lista de
/// alterações a serem enviadas para o servidor OData RESTful
procedure TRestODataAppView.FDMemTable1AfterPost(DataSet: TDataSet);
begin
if not FLoading then /// trata somente os registros alterados pelo usuário… (para não pegar os dados iniciais na carga da resposta do servidor)
case FState of
dsInsert: /// empilha os dados de INSERT – inserted
ODataDatasetAdapter1.AddRowSet(rctInserted, DataSet);
dsEdit: /// empilha os dados do POST – modified
ODataDatasetAdapter1.AddRowSet(rctModified, DataSet);
end;
end;
/// No ApplyUpdates do Dataset despachar para o servidor
/// as alterações armazenadas para serem notificadas
/// ao servidor
procedure TRestODataAppView.FDMemTable1BeforeApplyUpdates(DataSet: TFDDataSet);
begin
// envia os dados alterados para o servidor OData RESTful
ODataDatasetAdapter1.ApplyUpdates(nil, rmPATCH);
end;
procedure TRestODataAppView.FDMemTable1BeforeDelete(DataSet: TDataSet);
begin
/// empilha os dados a serem de DELETE – deleted a ser enviado ao servidor
ODataDatasetAdapter1.AddRowSet(rctDeleted, DataSet);
end;
procedure TRestODataAppView.FDMemTable1BeforePost(DataSet: TDataSet);
begin
/// guarda o estado da linha (dsEdit, dsInsert) para uso no AfterPost
FState := DataSet.State;
end;
procedure TRestODataAppView.FormCreate(Sender: TObject);
begin
/// um exemplo de como adicionar CustomHeaders a mensagem que será enviada ao servidor
IdHTTPRestClient1.IdHTTP.Request.CustomHeaders.AddValue(‘token’, ‘abcdexz’);
end;
procedure TRestODataAppView.Button1Click(Sender: TObject);
begin
FLoading := true; /// controle para não gerar linhas de alterações na pilhas
try
/// executa um GET no servidor RESTful
/// o servidor fazer um SELECT e devolve o conteúdo as linhas do SELECT
ODataDatasetAdapter1.Execute;
/// limpa alterações que estejam armazenadas
ODataDatasetAdapter1.ClearChanges;
finally
FLoading := false;
end;
end;
procedure TRestODataAppView.Button2Click(Sender: TObject);
begin
FDMemTable1.ApplyUpdates(); /// processa a alteração do Dataset
end;
[/code]