Nulo em Inteiro

Delphi

15/05/2011

Olá Pessoal, vejam se podem me ajudar
tenho uma classe de persistência, que ela lê o meio objeto preenchido e salva no banco
estou com um problema para identificar os campos inteiros nulos, vou citar um exempo
tenho minha classe aluno
type  TAluno = class    IDAluno:Integer;    Nome:string;    IDMatricula:integer; // neste caso seria uma chave estrangeira de outra tabela  end;

digamos que estaria cadastrando um aluno que nao tivesse matricula, entao eu iria fazer assim
aluno := TAluno.Create;aluno.IDAluno := 1;aluno.NomeAluno := 'FULANAO DE TAL'
e nao passaria nada no IDMatricula pq o aluno ainda nao esta matriculado, e qdo eu vou ler esse objeto para persistir no banco o IDMatricula que é uma campo inteiro assume como padrão o valor 0, qdo eu vou salvar dá erro de chave estrangeira pq logicamente nao existe MAtricula com código 0 cadastrado no banco..

nao achei nada parecido com o nullable do c# ou algo assim..

espero que possam me ajudar
Rafareis

Rafareis

Curtidas 0

Respostas

Marco Salles

Marco Salles

15/05/2011

No delphi convencional ainda não tem o suporte a tipos nulos nativos na linguagem. O nullable foi introduzido no
Delphi Prims ,  como muitos recursos do Prism aos poucos estão sendo adaptados para O Delphi , talves na proxima
Versão esteje presente.. Por enquanto vc tem que achar uma solução braçal para diblar este deficiencia
GOSTEI 0
Emerson Nascimento

Emerson Nascimento

15/05/2011

qdo estiver cadastrando atribua -1 ao IDMatricula. ao persistir os dados na base, verifique se o IDMatricula é -1 não não faça qualquer atribuição ao campo da tabela.


GOSTEI 0
Rafareis

Rafareis

15/05/2011

obrigado a todos que tentaram ajudar

olá Emerson, eu tinha pensado nisso, mas como minha classe de persistência é dinâmica fica difícil eu fazer esse tratamento, pois eu simplesmente posso tem um campo inteiro com o valor -1.
o que eu pensei foi colocar em todas as minhas classe que sejam inteiro mas que possam ser nulos (que é o exemplo citado assim, um campo ID de outra tabela que pode ser nulo) seta-los como tipo variant ao invés de integer. o que vocês acham da solução?

e você Marco, algum outra idéia para este problema?


vlw mais uma vez pela tentativa de ajuda..abraços

GOSTEI 0
Marco Salles

Marco Salles

15/05/2011

bem idéias são muitas . Mas depende muito do seu framework de persistencia . Poe exemplo vc diz :

"e nao passaria nada no IDMatricula pq o aluno ainda nao esta matriculado, e qdo eu vou ler esse objeto para persistir no banco o IDMatricula que é uma campo inteiro assume como padrão o valor 0, qdo eu vou salvar dá erro de chave estrangeira pq logicamente nao existe MAtricula com código 0 cadastrado no banco.."

E se vc conseguiss-se de fato passar null para esta propriedade ... Vc n~eo cairia no mesmo problema citado acima ????

..., qdo eu vou salvar dá erro de chave estrangeira pq logicamente nao existe MAtricula com código nullo cadastrado no banco.."

?????

Sabe . muitas das vezes precisamos definir as arestas de um Modelo ... Porque não o valor de -1 não pode representar
Matriculas inexistenstes ??? Porque não definir uma Mtatrcilua que tenha este valor para representar esta situação ???

Vc diz sobre variantes , deve lembrar que variants a uma perda de performance , por não terem o tipo identificado na
compilação mas sim em rumtime
GOSTEI 0
Rafareis

Rafareis

15/05/2011

Então Marco, como eu disse, a minha framework de persistencia é dinâmica eu nao sei em runtime se o campo e realmente o IDMAtricula ou qualque outra propriedade das minhas classes, o que eu sei é que o campo é do tipo inteiro, e eu posso ter qualquer outra propriedade do tipo inteiro que pode receber o valor -1, dessa forma eu nao conseguir identificar na minha classe de persistencia o que é para ser montado na query de inserção/update/delete entendeu?
e ja usando tipo variant, quando a minha classe de persistencia encontrar qualquer propriedade com este tipo e que estiver nula, ela simpelsmente pode ignorá-lo e nao compor as queries de inserção/update/delete, dessa forma serviria para todas as classes. No meu caso eu iria colocar em todas as minhas classes, como regra, propriedades que representar chaves estrangeiras teria que ser variant
Mas eu não gosto muito dessa solução pelo motivo que vc citou, a questão de performace, e deixar regras no desenvolvimento tira a flexibilidade que eu quero no meu projeto.
mas nao estou vendo outra solução para este problema, lembrando que este problema so me ocorre qdo eu tenho propriedades que representam chaves estrangeiras.
bom, esotu pensnado o que fazer ainda, se tiverem outra solução, ficarei grato.
abraços
Reis
 
GOSTEI 0
Marco Salles

Marco Salles

15/05/2011

Então Marco, como eu disse, a minha framework de persistencia é dinâmica eu nao sei em runtime se o campo e realmente o IDMAtricula ou qualque outra propriedade das minhas classes,


Sabe sim amigo ... Decorando a Classe vc pode obeter essas informações em RumTime
Procure por Custom Atributes ( Atributos Customizados )
Vc vai definir um Atributo e Decorar a classe a property IDMAtricula com este Atributo


( Acreditando que vc uses a nova classe de Rtti .... Porque falar em persistencia anted do Delphi 2010 é bem mais
complicado .

Ps ) Caso vc tenha vc não consiga volte a postar que talves de para fazer u exemplo simples , mas acho que
vc não terá dificuldade




GOSTEI 0
Rafareis

Rafareis

15/05/2011

Eu uso o delphi 2006 ainda, na verdade eu tinha parado de mexer com delphi há algum tempo..
portanto nao me atualizei nas novas versoes do delphi, sei que o delphi 2010 tem mtas coisas interessantes, que nao tinha nas versoes anteriores, estou fazendo utilizando os recursos que temos no 2006 mesmo. (sofrendo, ehhehehhehee) essa arte de reflexão das versões anteriores ao 2010 é bem engessado mesmo, mas ainda assim da para usar.
inclusive estava precisando fazer herança multipla, mas e impossivel nas versoes antigas, e li que na versão 2010 o delphi ja suporta isso
Não entendi como o decorator poderia me ajudar nessa situação, poderia me explicar melhor?
 
GOSTEI 0
Marco Salles

Marco Salles

15/05/2011

Eu uso o delphi 2006 ainda, na verdade eu tinha parado de mexer com delphi há algum tempo..
portanto nao me atualizei nas novas versoes do delphi, sei que o delphi 2010 tem mtas coisas interessantes, que nao tinha nas versoes anteriores, estou fazendo utilizando os recursos que temos no 2006 mesmo. (sofrendo, ehhehehhehee) essa arte de reflexão das versões anteriores ao 2010 é bem engessado mesmo, mas ainda assim da para usar.
inclusive estava precisando fazer herança multipla, mas e impossivel nas versoes antigas, e li que na versão 2010 o delphi ja suporta isso
Não entendi como o decorator poderia me ajudar nessa situação, poderia me explicar melhor?


Vamos por partes


inclusive estava precisando fazer herança multipla, mas e impossivel nas versoes antigas, e li que na versão 2010 o delphi ja suporta isso

Herança multipla so com interfaces e não apresentou diferenças entre as versões novas do delphi e a do delphi 2006 .. Vc consegue herença multipla implementando Interfaces . Na realidade a Borland incluiu interfaces no Delphi
para oferecer suporte ao COM da microsoft , mas podemos utiliza-la como um Recurso Extra

Por exemplo

type
 TminhaClass = Class ( TinterfacedObjeto , IntefaceA , InterfaceB , InterfaceC .....)


Não entendi como o decorator poderia me ajudar nessa situação, poderia me explicar melhor?

Neste ponto sim , o Delphi evolui e evolui muito . O novo RTTI , permite de maneira muito mais fácil a reflaxão de uma classe . Nesta Nova arquiteura foi acrescentado o CUSTOM ATTIBUTES . È uma forma de se acrescentar informações adicionais a uma propriedades , método  , classe , ou ate mesmo variavel ..E Esta informaçoes podem ser obtidas atraves de RTTI

Mas como ela pode te ajudar ???

Imagine que vc tenha definido um Custom Atributes por exemplo

type
NullableAttribute = class (TCUstomAttribute)
private
 FName:String;
public
 constructor Create(aNome:String);
 property Name:String read FName write FName;
end;

a partir deste Atributo vc decora a sua class

type  TAluno = class
   private
    IDAluno:Integer;    Nome:string;    FIDMatricula:integer; // neste caso seria uma chave estrangeira de outra tabela
 public
  [NullableAttribute('qualquer coisa')]
    property IDMatricul:integer read FIDMatricula write  FIDMatricula;
  end;


a partir do momento que vc decorou sua classe , vc vai consegui em RumTime saber não se o campo é  o IDMAtricula ,
mas vc vai poder saber se o Atributo deste campo desta classe é o NullableAttribute ... Se For vc vai analizar o valor
do campo , se for -1 , simplesmente não faz nada , se for positivo persiste ele no banco

Vc deve estar perguntado : Mas e os outrso inteiros das outras classes que podem ser negativos ???

Para os outros inteiros vc não vai Decorar a classe então nunca o ATRIBUTO deste campo será NullableAttribute... Então não
caira no Teste de condição












GOSTEI 0
Rafareis

Rafareis

15/05/2011

Sim, eu sei disso perfeitamente, a gente consegue fazer herança multiplas usando interface, isso ja vem no delphi há mto tempo...
mas alguma linguagens de mais baixo nivel, oferecem a herança multiplas, coisa que nao existe no delphi..

este classe TCUstomAttribute só tem a parti da versao 2010?

valeu mais uma vez pelas dicas Marcos
GOSTEI 0
Marco Salles

Marco Salles

15/05/2011

Sim, eu sei disso perfeitamente, a gente consegue fazer herança multiplas usando interface, isso ja vem no delphi há mto tempo...mas alguma linguagens de mais baixo nivel, oferecem a herança multiplas, coisa que nao existe no delphi..este classe TCUstomAttribute só tem a parti da versao 2010?valeu mais uma vez pelas dicas Marcos


O que eu quiz dizer foi o seguinte .. Eu particularmente não sei e desconheço o suporte a Herança multipla a
partir do Delphi 2010 ... Seria uma grata surpresa saber que se pode obter este resultado a partir do delphi 2010
mas não li e não vi nada a respeito. Alguem me corrija se tiver errado e me passe um link caso contrário

Algumas linguagens de fato suporta herança Multiplcas , isto é ponto


herança multiplas usando interface, isso ja vem no delphi há mto tempo. Isto também é ponto e foi introduzido
a interface para ter suporte a COM .. Também é notório


este classe TCUstomAttribute só tem a parti da versao 2010?

Bem , de maneira difundida sim .. Vc sabe que a comunidade não assimila todas as novidades de uma so vez
Vai passar uma vida para a gente começar a usar efetivamente JSon , failover , calback no DaTaSnap por exemplo
Igual o clientDataSet quando foi introduzido acho que no Delphi5 (versão enterprise se não me engano ).Mas
foi no delphi7 que todo mundo se familarizou com ele. Falo isto porque a classe TCUstomAttribute ,  esta sendo largamente difundida na Versão 2010 do Delphi ,porém ela pode ter sido definida no Delphi 2009 ou mesmo no Delphi 2007 . O fato é que não tive conhecimento desta classe em versões anteriores ao Delphi 2010 , mas não descarto esta hipótese apesar de acha-la vaga

Bem , mas ja que vc não tem estas "novidades" e esta se virando como pode , deve ter solução mais
orientada a objeto ( mesmo que mais dificil de se alcançado )  na sua versão do Delphi .

Suas Classes de persistencias utilizam a TypeInfo ??? Elas são dificieis de serem implementadas ???
talves alguem possa  opinar baseado naquilo que vc consegui ate agora.. Mas vc deve coloca-las
( se não for grande demais ) ou de uma forma simplificada para tentar entender o que vc fez ..






GOSTEI 0
Rafareis

Rafareis

15/05/2011

Olá marco
desculpe a demora pra responder, eu ando um tanto ocupado..
bom, a priori estou colocando todas as propriedades que representar uma foreingkey como variant, eu resolvi o problema com uma solução parcial
estou com outra duvida, vamos ver se consegue me ajudar

a estrutura do meu sistema esta dessa forma:                                                     TScreenBase (Tform)    TIputForm(TScreenBase) -  TSearchForm (TScreenBase) 
TConAluno(TSerarcForm) .. e assim por diante



então no create do TScreenBase  eu faço isso
inherited Create(AOwner);onCreate := FormCreate;


bom este form fConAlun que herda de TSerarcForm e que herda de TScreenBase no create dele eu preciso iniciar uma propriedade entao eu faço isso

 ClassName := 'Aluno'; inherited;
teoricamente ele teria que executar o create da minha classe filho correto?? ou estou errado??

funciona assim quando ao inves de ter uma classe TScreenBase eu crio um form base que tem a mesma função..

onde eu estou errado?? se nao tiver clara a minha pergunta por favor digam que eu tento reformular..
muito obrigado
  

GOSTEI 0
Marco Salles

Marco Salles

15/05/2011


onde eu estou errado?? se nao tiver clara a minha pergunta por favor digam que eu tento reformular..


desculpe mas não entendi. Se algumem entendeu sinta-se a vontade para participar pois o tópico é publico
GOSTEI 0
Wilson Junior

Wilson Junior

15/05/2011

qdo estiver cadastrando atribua -1 ao IDMatricula. ao persistir os dados na base, verifique se o IDMatricula é -1 não não faça qualquer atribuição ao campo da tabela.




Olha, sugiro fazer isto que o Emerson colocou, caso não te resolva, me diga como vc está fazendo para gravar estes dados.

Espero ter colaborado.
GOSTEI 0
Rafareis

Rafareis

15/05/2011

Olá wilson, obrigado pela ajuda

então, não dá para eu fazer como o emerson sugeriu porque a minha classe de persistência é dinâmica.. eu passo o meu objeto preenchido e ela faz a persistência.. eu não tenho como saber se a propriedade é referente a uma chave estrangeira (até dá, como nosso amigo marco disse eu poderia decorar a propriedade, mas isso infelizmente nao esta disponível na versao 2006 do delphi, vesao na qual estou usando) e não poderia tratar esse caso passando -1, como foi mencionado, porque como a classe é dinâmica , nao poderia tratar todos os campos inteiro dizendo que qdo o campo estiver -1 eu o   ignoro, pq pode haver alguma outra classe que tenha um propiedade que seja do tipo inteiro e que permita receber -1 (afinal é um inteiro tbm certo?).. então, como solução paleativa defini uma regra de desenvolvimento, que toda classe que tenha uma atributo que represente uma chave estrangeira eu o defino como variant, desse forma minha classe de persistencia sabe que os campos que sao deste tipo representam uma chave estrangeira e assim consigo fazer esse tratamento. Não é a melhor coisa a se fazer, mas por enqto e a melhor solução
entendeu?? caso nao tenha entendido, fico a disposição para esclarecer duvidas

Marco, o problema que deu foi no delphi, questoes de herança de formulário... deve ter corrompido algum arquivo dfm do meu formbase e as outras telas nao conseguiam herdar os metodos deste formbase, e eu estava achando que era algo relacionado a implementaçao, por isso solicitei ajuda de vc´s, mas depois de mtas  horas batendo cabeça descobri que o delhi tinha corrompido , de alguma forma esses arquivos, e tive que recria-los, e reinstalar o delphi, pq estava danto uns erros muito doidos, nao so nesse projeto como em todos os outros... a partir disso consegui fazer funcionar novamente...

mais uma vez obrigado a todos por ajudarem... grande abraço
GOSTEI 0
Leonardo Santos

Leonardo Santos

15/05/2011

Se o campo não estiver marcado como Not null no banco, basta você dar uma .Clear no campo e estará tudo resolvido!
Exemplo: CdsAlunoIDMatricula.Clear;
Espero ter ajudado!
GOSTEI 0
Guilherme Wiethaus

Guilherme Wiethaus

15/05/2011

Eu utilizo o seguinte em meu sistema, talvez esta ideia ajude.

Eu tenho um registro de indice único e sempre começa em 1. Zero é porque nao houve entrada ou o registro é novo. Assim só é permitido gravar números maiores que zero no banco ou diferentes de nulo.

Bom, como seria inteiro x null.

Escrever no campo de uma tabela:

if variavel = 0 then 
   adodataset1.fieldbyname(Indice).AsVariant:= Null
else
   adodataset1.fieldbyname(Indice).AsInteger:= variavel;


como no campo da tabela é permitido gravar de valores maiores que zero eu assumo que zero em uma variavel é como se fosse Null no campo da tabela.

se no campo de sua tabela possuir nulo como valor e o campo é do tipo inteiro, o que ira retornar se fizer isto:

variavel:= adodataset1.fieldbyname(Indice).AsInteger;

o valor da variavel será zero

mas se fizer isto

var
  variavel: Variant;
....
variavel:= adodataset1.fieldbyname(Indice).AsVariant;


variavel retorna null;


Abraços.
GOSTEI 0
POSTAR