Luiz Escobar wrote:

> Onde eu implemento uma TRANSAÇÂO ? se der pau para fazer um ROLLBACK.....
> TIPO usado seu exemplo... :
> 
> try
>    cliente.insert;
>    Cliente.Nome := 'fulano';
>    contrato.insert;
>    Contrato.data := 'hoje';
>    nota.insert;
>    nota.id := '00001';
>    itens.insert;
>    itens.nota := 'item 001';
> 
>    cliente.save;
>    contrato.save;
>    nota.save;
>    itens.save;
> 
>    ALL.APPLYUPDATE ( -1 ); <<- e somente aqui salva tudo e se der um pau
> 
> exception 
>     all.roolback();  <<-- volta tudo sem cadastrar nadinha nos bancos !!!
> end;

O seu modelo de classe sabe que itens pertence a nota, portanto 
itens.save não existe.

Eu não entendi direito o que você quer dizer com contrato, mas quanto ao 
resto, fica assim:

Cliente := TCliente.Create; // esqueça o conceito de Insert
Cliente.Nome := 'Fulano';

Se você estiver preenchendo na tela, pode deixar que o Presenter que 
controla a Combo dá a opção de você criar um novo cliente. Estou falando 
de um exemplo hipotético totalmente em código. Continuando:

Cliente.Save;

Nesse ponto eu criei um cliente e salvei, mas eu poderia pegar um do banco:

Cliente := TCliente.Retrieve(IDCliente);

IDCliente não vem por mágica. Você pode usar uma PressQuery para 
consegui-lo -- o que por sinal te traria a própria instância Cliente e 
nem precisaria de Retrieve. Ainda assim, apenas exemplo em código, um 
Presenter faz isso pelo usuário e pelo programador com um pé nas costas.

Continuando - o que importa é que Cliente agora aponta para o cliente 
que eu quero usar.

Nota := TNota.Create;
Nota.Cliente := Cliente;
ItemNota := TItemNota.Create;
ItemNota.Quant := 10;
Nota.Itens.Add(ItemNota);
Nota.Save;

Liberando memória -- apenas memória, os objetos já estão no banco.

Nota.Free;
Cliente.Free;

Claro, faça isso dentro de blocos try/finally. Itens? Não precisa, itens 
é parte de Nota e não deve ser destruído.

Pronto. Sua nota foi salva junto com os itens, e apontando para o seu 
cliente, tenha ele sido criado ou trazido da base. Isto está simulando 
regras de negócio que funcionam em eventos independentes do que o 
usuário esteja cadastrando. Mas se você criou um formulário para 
preenchimento de nota, então precisa apenas disto:

TNotaEditPresenter.Run;

e aqui o usuário pode escolher o cliente, ou criar um novo caso ele não 
encontre, incluir itens, etc., etc. e o botão OK irá disparar o .Save 
deste objeto.

O cache é feito pelo objeto de negócio. Quando você executa

Nota.Cliente := Cliente;

ou ainda

Cliente.Nome := 'Nome';

isto é guardado no objeto de negócio, apenas em memória. Quando você 
executa:

Nota.Save;

todas as queries necessárias para gravar a nota, inclusive seus itens, 
são criados pelo OPF. Se ocorrer uma falha na transação, ela é cancelada 
e seu objeto permanece como 'ainda não salvo'. Mas isso não é problema 
da regra, é um problema do OPF e será reportado com uma exceção. O que 
você pode fazer é registrar um serviço de mensagens para traduzir 
algumas mensagens de erro que você queira (em desenvolvimento). Enfim, 
esquece transaction, esquece rollback, esquece qualquer coisa que não 
seja relacinado estritamente com regras de negócio.

Claro que você pode precisar gravar dois ou mais objetos em um único 
contexto transacional. Não é comum acontecer, mas pode. Veja que isto 
não se aplica a Cliente x Nota -- se o cliente for salvo e der pau pra 
gravar a nota, o cliente está íntegro, a nota não tem nada que ver com 
os dados dele. Enfim, o exemplo:

PressDefaultPersistence.StartTransaction;
try
   Obj1.Save;
   Obj2.Save;
   PressDefaultPersistence.CommitTransaction;
except
   PressDefaultPersistence.RollbackTransaction;
   raise;
end;

Este código fica implícito quando você chama .Save fora de um contexto 
de transação. Ou seja, sempre existe segurança, nada é feito nas coxas.


>>>> Pra quem acha que EDIT´s são melhores que DBEDIT´s, isso ai Fudeu com tudo 
>>>> mesmo porque os controles ficaram mais ainda longe das mãos dos 
>>>> programadores.... não que eu não ache isso maravilhoso, muito pelo 
>>>> contrario, quanto menos codigo melhor...
> 
>> Que controles você precisa?
> 
> EU !, De nenhum.... Quando menos tiver que me preocupar com controles 
> disso-daquilo melhor, ganho em produtividade... eu disse PRA QUEM ACHA, 
> afinal a discusão era DBWARE ou não...  

Pra quem achar, basta dizer o que precisa, pois sempre haverá uma forma 
de fazer.

>>>> BOM mas o que o OPF do RETRIEVE usou para se ligar ao BANCO ? não foi um 
>>>> DBWARE ? tipo um TTABLE ? TQUERY ? TDATABASE ? e para visualizar as 
>>>> coisas, vou ter que fazer um label1.caption := cliente.nome ? 
>>>> Explique mais, ou mostre onde posso conseguir mais coisa.... to começando 
>>>> a gostar do bixim.... 
> 
>> Cliente := TCliente.Retrieve(ID);
>> TClienteEditPresenter.Run(Cliente);
>>
>> Em duas linhas você traz o cliente, mostra pro usuário, o usuário altera 
>> o que quer, clica OK, e o que o usuário alterou é enviado para o banco 
>> em uma única transação.
>>
>> TClienteEditPresenter.Run;
>>
>> Em uma linha você faz tudo o que eu falei acima, mas ao invés de 
>> alterar, você cria um novo cliente. Detalhe - nem precisa se preocupar 
>> em criar instância de coisa nenhuma. Nem destruir (use o FastMM se você 
>> não acredita).
> 
> 
> Acho que vou precisar experimentar para ver como é o trem ai... pra continuar 
> a thread.. hehehhe....
> Pois tem que ter uma ligação  pra esse RUN ai uai... ele tem que estar ligado 
> a um FORM que vc construiu... o o negocio é magico d+
> Vejo um exemplo que pra LOGIN o cara faz uma aplicação completa agora vc vem 
> com 2 linha que abre, localiza, edit, salva, create, destroiu e nem ligou ela 
> ao banco ele adinhou tudo... ai ficou vago... heheheheh....

Este Presenter está registrado, aí está a mágica. Veja o aplicativo 
exemplo do Press, mexa um pouco com ele.

>> O framework está estável, como eu já te disse, tenho ele em produção.
> 
> 
> BLZ vamos ver no que vai dar.....  
> Mas assim como troquei o CLIPPER por DELPHI vou acabar trocando o DELPHI por 
> PHP um dia..... ;-)

E o desktop? E nem te preocupa, eu sou amarrado em PHP e ainda vou fazer 
uma ponte entre essa mágica e código para web. Mas n-tier ainda tá na 
frente.

--
João Morais

Responder a