sexta-feira, 31 de dezembro de 2010

Genexus dos Sonhos!

É estranho como temos a capacidade de criticar coisas prontas, mas a incapacidade de criar coisas novas, ou me expressando melhor, como nossa velocidade em criticar é muito maior que a velocidade de criar. Tenho observado essa característica humana ao longo da minha existência, e o pior que muitas vezes recorro a isso também com uma eficiência absurda.

Por favor, entendam esse POST não como crítica, mas como criação, pois o objetivo aqui é contribuir com idéias... E há certo tempo tenho sido incomodado por um sentimento de sugerir idéias para melhoria do Genexus. E entendo a Artech como uma empresa diferenciada, inclusive muito atenta às necessidades da comunidade, provendo evolução constante da ferramenta, também busca a ferramenta ideal. Portanto, ai vai minhas inocentes contribuições.

Linguagem:


1) Ponto-e-virgula: Acredito que a principal necessidade seria a unificação das diversas linguagens e formatos utilizados, e que vem dificultando um pouco o aprendizado da ferramenta. Quero dizer aqui o seguinte, em certos lugares se obriga a colocar ponto-e-virgula e em outros não. De vez em quando isso incomoda um pouco, como por exemplo, quando se escreve uma expressão gigante numa Condition de Grid e, ao se esquecer do tal ponto-e-virgula, se perde tudo.

2) If: é outro recurso que poderia ser unificado, por exemplo, o formato utilizado em fórmulas não é o mesmo que se pode escrever na aba EVENTS, seria muito interessante se o formato simplificado das fórmulas pudessem ser utilizados nos eventos e vice-versa.

3) Sou programador C, e apesar da grande maioria não gostar muito dessa praia de ondas bravas, acredito ser uma das melhores já criadas até hoje, principalmente devido ao recurso de simplificação. Como a possibilidade da criação de blocos com as chaves { ... } em comandos de controle. Isso simplificaria um pouco a programação, evitando-se os EndIf, EndFor, ....

4) Os operadores ++ e -- de C também são muito interessantes

5) O Ricardo Oliveira postou uma idéia muito interessante que eu também compartilho da mesma idéia, que é a utilização de blocos para a programação nativa (csharp, java, ...) , assim como acontece atualmente, com as sections [web], [win], [bc].

O formato seria algo como:

[csharp]
{

...

}

Isso permitiria a construção de código de forma mais elegante, e apesar do recurso de programação nativa não ser muito indicada, de vez em quando salva.


Interfaces:


1) Templates: Permitir ao próprio programador definir templates para a geração de FORM´s em transações. Ou seja, define-se um modelo HTML, e indica-se o local onde o Genexus inseriria os controles dos diversos atributos da transação (algo semelhante ao que ocorre nas masterpages atuais). Isso possibilitaria a geração de interfaces totalmente otimizadas e de acordo com as regras que o próprio mercado define. Por exemplo, atualmente difunde-se o uso de <div> e <span>em substituição às <table>, consideradas obsoletas, visto que os primeiros aceleram a velocidade do browser.

De certa forma, a definição de templates permitiriam a interferencia do Analista no próprio funcionamento do Gerador, otimizando-o para as suas necessidades.

2) Controles distintos para um mesmo atributo: Isso de certa forma já acontece hoje, quando se define o tipo EDIT com Description na estrutura da transação (Ver POST Anterior), mas seria interessante expandir um pouco mais esse recurso, com novas propriedades na estrutura da transação para se definir o tipo de controle a ser gerado nas situações:
  • O atributo chave primária em sua transação original: EDIT
  • O mesmo atributo como chave estrangeira em outra transação: EDIT com Description, Dynamic List Box ou Dynamic Combo Box,...
  • O mesmo atributo como chave estrangeira em um GRID: EDIT com Description, Dynamic List Box ou Dynamic Combo Box,...
Atualmente temos várias propriedades para designar tipos distintos de titulos (Title, Contextual Title, Column Title), que tal expandir esse mesmo mecanismo para se definir tipos de controles.



3) Relatórios dinâmicos: sou fã da programação dinâmica, e tudo que permita influenciar um determinado modelo em tempo de execução, adequando-o a realidade do próprio usuário. Talvez um vício da programação em C, onde tudo era possível de se construir dinamicamente. Deixe te dar um exemplo, que tal se tivéssemos na aba layout de relatórios a possibilidade de incluir e remover dinamicamente controles (atributos, variáveis,...), ou seja, que pudéssemos definir quais controles estaríamos interessados em apresentar em determinada situação. Num grid por exemplo, poderíamos gerar um relatório dinâmico, a partir das colunas selecionadas pelo próprio usuário.

4) Dinamismo na interface gráfica: Permitir definir certos controles na interface web que sejam carregados através de Ajax. Por exemplo, utilizando-se vários combos dinâmicos o controle retorna ao servidor e toda a interface é carregada novamente. Poderia haver um processo em que ao trocar as condições de filtro, de um dynamic combo, e o browser acionaria Ajax para recarregar apenas o que foi influenciado pela mudança.

Programação


1) Biblioteca de procedimentos: Nas linguagens tradicionais (C por exemplo) tínhamos as LIB's que eram as coleções de procedimentos que podíamos importar em outros projetos. Java possui Classes que podem ser guardadas em WAR´s e utilizadas em outros projetos.

Genexus poderia permitir a criação de classes de procedimentos gerados para utilização em outras Kb's sem que fosse necessário utilizar o recurso exportar e importar xpz's. Lembrando que este mecanismo atualmente faz com que os procedimentos sejam compilados e gerados novamente. Com bibliotecas teríamos uma melhoria significativa no desempenho do projeto, pois o que está pronto não precisaria ser reconstruído.

Tenho duvidas se com External Object isso não se encontra disponível, preciso verificar.

2) Operador NOT IN:  Em situações de pesquisas na base de dados em que se busca registros que se encontram em uma tabela, mas, não em outra, poderiam ser resolvidas com o operador NOT IN, ou seja, a diferença entre dois conjuntos. Atualmente para programar isso é necessário dois for...eachs, no mínimo, gerando processamento no programa ao invés do database, o que torna a aplicação mais lenta.


Modelagem

1) Subordinação Lógica: Em algumas ocasiões o Genexus, ao modelar automaticamente a base de dados, cria relações automáticas que não apontam na direção que o desenvolvedor pensava inicialmente, gerando controles de Integridade Referencial sobre tabelas que não possuem relação direta. Pois ele sempre que encontra relação, aponta para o conjunto de índices mais restritivos (completos).

Talvez fosse interessante, em alguns casos, permitir (via configuração) que o desenvolvedor escolhesse a relação que deseja gerar entre tabelas.

Bom, por enquanto é só, talvez futuramente possamos acrescentar alguma coisa a mais na lista.

Controle sobre os Controles da Interface

Esse titulo é um tanto quanto estranho, mas serve bem ao propósito deste POST, as vésperas de um novo ano, espero que com muitos POSTS.

O objetivo aqui é como podemos ajustar a interface Genexus, de forma que a própria ferramenta gere para nós uma interface interessante, sem que tenhamos que alterar formulário por formulário, muitas vezes perdendo a automação automática.   E uma característica conhecida nas interfaces Genexus é que se ao se definir alguma coisa na estrutura da transação, todo o sistema será afetado por essa modificação.  E isso ocorre com praticamente tudo, exceto a seleção do tipo de controle da interface web.

Ao se definir qualquer controle diferente de EDIT na estrutura de uma transação para um atributo do tipo chave primária, essa definição não afetará a interface da própria transação, mas todas as demais que utilizam esse atributo.  Por exemplo, na transação Pais, definimos na estrutura da transação, para o PaisId, o tipo EDIT com Description. 

Na imagem a seguir é possivel visualizar o controle EDIT com Description selecionado para PaisId, e o resultado na interface.
No entanto, na interface de cadastro de Paises, não ocorre alteração no controle de entrada de PaisId, e o mesmo continua como um EDIT simples. Já na interface de Clientes, o controle de PaisId passa a ser do tipo EDIT com Description.
Quanto a utilização em GRID, ocorre que PaisId também é apresentado em forma de EDIT com Description, não sendo portanto necessário apresentar PaisNome.  Mas atenção, PaisNome tem que constar no GRID para que a informação apareça corretamente (Visible=false, resolve a questão).

Com isso é possível usar os recursos do próprio Genexus para obter soluções interessantes com nenhum  esforço, ainda mais nesse período de festas, pois, temos outras coisas mais importantes pra fazer!.

domingo, 28 de novembro de 2010

Gxui apresentando Internal Error: Invalid Render

Gxui é um recurso fantástico para implementar interfaces, mas devido a falta de documentação, de vez em quando, temos algumas dificuldades.

A última diz respeito a mensagem Internal Error: Invalid Render, aparecendo na construção do Web Panel.  Gerando um grave inconveniente de não se permitir que se visualize a interface gráfica. Ou seja, impossibilitando a programação.

Para corrigir o problema, instale novamente o gxui, realizando o download e e em seguida o restart do Genexus. Ao abrir novamente de um Build All nos objetos, que a mensagem desaparece.

Quanto ao aparecimento do erro, foi após instalar um Pattern que mudou o posicionamento dos UC´s do gxui da paleta de ferramentas, ou seja, creio ser um problema de versão.

quinta-feira, 11 de novembro de 2010

Show in Default Form...

Voce conhece a propriedade Show in Default Form?

Por não conhecer, toda vez que tinha atributos de controle na interface, como por exemplo, flags que indicavam o registro apagado, datas de controle, totais de itens, e coisas do tipo.  Programava no evento Start uma propriedade PedidoItensTotal.visible = 0.  E não apenas isso como tambem tinha que apagar o rótulo do atributo na interface, ou seja, a interface original saia do padrão justamente por atributos de controle.

Recentemenete, resolvi procurar um recurso de remover atributos indesejados na interface do usuário, e não é que existe a tal propriedade  Show in Default Form. Seu funcionamento é remover os atributos marcados como false da interface gerada.

Muito útil.

quarta-feira, 3 de novembro de 2010

Obtendo a Resolução de Vídeo do Usuário

Simples, uma aplicação Web precisa ser apresentada no navegador do usuário, que é um programa complexo, cheio de recursos, mas diferente de um fabricante a outro, e para complicar ainda mais é importante que a informação que você quer apresentar se adapte a resolução do monitor de seu cliente.

Genexus facilita a vida porque praticamente resolve tudo sozinho na questão de incompatibilidade de navegadores, ficando poucas situações que de fato dependem de programação especial.

Este exemplo explora Javascript para descobrir a resolução de vídeo na máquina do usuário, e sua utilidade, não preciso nem mesmo explicar, não é!

Javascript

É uma linguagem que opera no navegador, de sintaxe simples e cheia de recursos que podem ser explorados para se produzir interfaces especiais.  Genexus não atrapalha nesse sentido, permitindo que se agregue funcionalidades em Javascript sem mistérios.

Esse exemplo explora o conceito de DOM do Javascript para devolver parâmetros para o Genexus, sendo que esses constituem a resolução de vídeo do usuário.  Não estou dizendo a dimensão da janela (maximizada, minimizada ou ajustada pelo usuário), mas a própria resolução de vídeo.  Se deseja as dimensões da janela também é simples, mas não vou explorar isso aqui.

Funcionamento

Ao executar uma operação de login no sistema, gravamos em sessão as dimensões da janela (width e height).  Todas as interfaces seguintes podem explorar esse recurso para dimensionar sua área.

Utilizamos o conceito de agregar no da página um evento onload que chama a função responsável por obter e armazenar as dimensões em duas variáveis Gx criadas no formulário.

Ao finalizar o processo, lë-se as variáveis e cria-se a sessão. Simples!.

Para isso criamos inicialmente um webpanel, com quatro variáveis: &usuário, &senha, &screenwidth e &screenheight, sendo as duas últimas mantidas ocultas do usuário
Sem segredos na criação das variáveis, a resolução pode ser Numeric(4) as demais não são importantes no exemplo.

Em seguida utilizamos um TextBlock para definir os comandos Javascript que tratam de obter a resolução da interface (linha 9 e 12, abaixo), e a programação do evento onload na tag da página (linha 5 a 13: função, linha 15: a inclusão no body).


Finalmente, ao se pressionar Entrar, a criação da sessão (linhas 20 e 21) , e o tratamento do login do usuário, (a partir da linha 24).


 O resultado
Ao se executar o programa, e ao se pressionar ENTER.


Ocorre a criação da sessão, e a mensagem de boas vindas apresentando a resolução obtida.


Você pode utilizar esse recurso para programar Javascript com Genexus, ou mesmo estendê-lo para obter uma estatística da resolução de seus usuários, com certeza te auxiliará na geração de interfaces adequadas ao seu público.

Agora, o pior é a resolução do meu vídeo 1366x768, fala sério, já viu isso? nem mesmo eu sabia .

terça-feira, 19 de outubro de 2010

Criando um Menu Recursivo (revisado)

Às vezes o mais complexo é resolvido com coisas simples, na verdade me parece que essa é uma regra da natureza, pois quanto mais complexa é a tentativa, mais distante se está da solução. Claro que quando falamos de programação de computadores, essa regra é quebrada de vez em quando, principalmente quando se depara com algoritmos com certo grau de dificuldade.

E na classe dos algoritmos mais estranhos, e que faz com que os programadores pensem duas vezes, encontram-se os recursivos. Ou seja, aqueles que por alguma razão precisam chamar a si próprios.

Acontece que uma das aplicações mais interessantes desses algoritmos, se encontram exatamente os menus de opções, e planejar um bom menu para o usuário é uma das tarefas importantes do desenvolvimento, para dar acessibilidade, organização e clareza nas operações do sistema.

A boa notícia é que Genexus é 10! e alguns programadores muito bem intencionados nos deram todos os recursos para programar um menu recursivo, sem muito esforço, portanto, cabe aqui apenas o direcionamento para os recursos corretos.
Entao, maos na massa e um pouco de paciencia para entender os elementos do menu.
 

1. JSCookMenu:

Esse é um controle muito pratico, que possibilita que se construam menus na interface web de forma muito interessante com controle sobre as classes CSS, ou seja, estilos, imagens, ...

Para carregar o JSCookMenu é necessário utilizar uma SDT, que já é recursiva por natureza, pois os Itens (Item) são na verdade ramos da própria SDT, como pode ser visto abaixo (veja o Type).

O menu possui uma variável do tipo coleção do SDT JsCookMenuItem que ao ser carregado apresenta as opções no controle, se olhar nas Variables verá que foi incluida uma variavel chamada &MenuDataCollection para esta finalidade. Portanto, para se carregar um item no menu teriamos que programar algo como:

 

&JSCookMenuItem = new()
&JSCookMenuItem.Title = 'item'

&JSCookMenuItem.UTL = 'http://www.gotoitem.com/itemfolder/item'
&MenuDataCollection.Add(&JSCookMenuItem)

 
Desta forma para cada item a ser incluido no menu teriamos que gerar um conjunto igual a este de codigo.Se não entendeu este código melhor voce estudar um pouquinho a respeito de Structured Data Type e também Collections.

 


2. Data Provider:

Para programarmos o menu recursivo usando a programação apresentada anteriormente seria bastante complexo, com for each, procedure recursiva, enfim, vamos aproveitar o exemplo para falar de mais um recurso interessante que temos a nosso favor.
 
A Artech comemorou muito o lançamento deste recurso no Genexus, é não é pra menos, com poucas linhas de ‘código’, se carrega uma SDT complexa como a apresentada, bastando declarar o conteúdo que desejamos em cada elemento da estrutura.

Para ser mais claro, o DP abaixo dá conta do recado e substitui a programação da procedure mais complexa, apenas usando o recurso de declarar o conteudo que queremos.



Os elementos incluidos nesta programação são atributos que estão em uma tabela Menu, e prontos para irem para nosso controle na interface (MenuTitulo, MenuTarget, FatherMenuId, ...)


Um detalhe que nao explicamos da primeira vez aqui foi a regra PARM necessária para este Data Provider funcionar, que deve ser:


Parm(&FatherMenuId, &FatherMenuItemId);


Falando em recursividade, se observar bem verá que existe um elemento na estrutura (childs) que chama o próprio Data Provider (JsCookMenuProvider1), ou seja, o SDT foi criado para funcionar de forma recursiva.


Quando este artigo foi escrito pela primeira vez, a idéia era uma tabela mais complexa, agora analisando com calma, a tabela Menu poderia ter sido criada mais simples apenas com os atributos:
  • MenuId
  • MenuTitulo
  • MenuUrl
  • MenuPaiId (subtipo apontando para MenuId)
 

3. Web Panel:

Aqui a coisa é simples, somente inclua um user control JSCookMenu na interface, e em seguida carregue a variável &MenuDataCollection com o nosso DP recursivo. Passe o parâmetro 1,1 na ‘primeira chamada’, e no evento Start do Webpanel chame o MenuSample.





4. O Resultado:

O resultado alcançado com esse Data Provider é bem legal, com as opções principais, sub menus e por ai vai, nao existe limite para organizar os niveis no Menu, pois, lembre que é recursivo.

Temos ai um recurso de árvore!! Fala sério, ficou legal, hein!!



5. A Árvore:

Observe que a parte programável acabou! E não gastamos muito para chegar aqui (Uma transação Menu, Um DataProvider carregando uma coleção do tipo SDT JSCookMenuItem), e você deve estar se perguntando cadê a procedure, onde esta o codigo fonte necessário para se carregar a coisa?. A resposta é que o Data Provider faz tudo, é uma 'procedure declarativa', e pode funcionar ainda como caracteristica recursiva.


Se não temos muito o que fazer com o programa então vamos explicar à parte mais difícil que consiste em alimentar o monstro, ou seja, como armazenar e carregar informação recursiva que alimente o DP e o JSCookMenu.



Para isso vou recorrer a um desenho de árvore mesmo, que talvez simplifique um pouco a visão para você. Veja que pendurado no nó 2 temos os itens (5, 6 e 7), e no nó 6 os itens (8 e 9). Outro exemplo, pendurado no nó 1, temos os nós (2, 3 e 4), e assim por diante. Entenda que o Menu pode ser organizado desta forma, bastando voce escolher onde vai pendurar as coisas.

Para os ‘puristas’ e mais exigentes, pode-se dizer que esta árvore não é binária, portanto, para cada nó, temos vários que podem estar conectados.



Em termos de dados podemos dizer que precisamos apenas de um numero para definir o nó e outro para indicar a qual nó este pertence. Ou seja, nó=7, pertence ao nó=2. E por ai vai.
]

Portanto, simplificando a coisa, precisaremos de uma tabela com os seguintes dados, para produzir o exemplo anterior:




E o que a tabela tem de especial? Apenas um campo recursivo chamado FatherMenuId e FatherMenuItemId que aponta para MenuId e MenuItemId, respectivamente. Observe que utilizei dois números para indicar um nó. Entenda o primeiro como grupo e o segundo como item do grupo, tipo uma idéia para organizar menus por grupos de usuários.


Aqui também faltou na explicação que para apontar FatherMenuId e FatherMenuItemId para MenuId e MenuItemId é necessário um objeto chamado Subtipo no Genexus.



6. Transação:

Claro que estamos no Genexus, e para que tudo se complete é necessária uma transação que grave os dados. Para isso temos uma estrutura simples:




Sendo que FatherMenuId e FatherMenuItemId são subtipos que apontam para MenuId e MenuItemId.



Agradecimentos e Conclusão

Portanto, para se criar um menu siga os passos:
  1. Crie uma transação Menu
  2. Crie um WebPanel e inclua nele o controle JSCookMenu
  3. Crie um DataProvider para carregar o SDT JsCookMenuItem
  4. Chame o DataProvider no WebPanel
Se voce usar sua imaginação poderá entender que este mesmo conceito pode ser usado para tratar de coisas diferentes, como por exemplo uma árvove hierárquica de familia, controle genetico de animais, ...


A conclusão aqui é simples, Genexus proporciona uma programação em árvore, complexa, com poucas linhas de código no Data Provider, então, reclamar do que? Genexus é 10!



Já o agradecimento é complexo, porque tantas pessoas participaram da criação do JSCookMenu, do Genexus, Transação, Subtipo, Data Provider, treinamento da Artech, ... que fica impossível identificar todos, e para não deixar ninguém de fora desta, então vamos apenas dizer:
OBRIGADAO!!!



Se quiser saber um pouco mais sobre recursividade em Data Provider, pode dar uma olhada no link: http://wiki.gxtechnical.com/commwiki/servlet/hwiki?Recursive+Data+Providers,

sexta-feira, 8 de outubro de 2010

GUG São Paulo

Somente para os interessados em conhecer um pouco mais a respeito de Genexus.  Dia 21/10/2010 teremos a nossa habitual reunião do GUG, cujo tema central foi definido como GXFlow. Fica aqui o convite para participar.

Maiores informações: http://gugsaopaulo.blogspot.com/

sexta-feira, 24 de setembro de 2010

Perdendo um pouco de tempo

Não sei se você compartilha do mesmo sentimento,  talvez já tenha observado que programar computadores de vez em quando não faz muito sentido.  Se perde muito tempo e no final das contas, sempre devido a alguma coisa muito estupida, que por alguma razão, claro que inexplicada, sempre acontece.  O engraçado é que quando a coisa 'flui' o sentimento é oposto, mas quando 'enrosca' dá vontade de mudar de profissão.

Esse post, foi meio dificil de escrever porque apesar da situação ser real, ou seja aconteceu, é tão inusitada que talvez você nunca a veja.  Ou mesmo, caso tenha passado por isso, deve ter desistido logo e passado para outra abordagem, e de certa forma desviado do problema.

O fato é que programando uma interface Web que chamava uma janela com &window.open(), de vez em quando, a tal não abria.  E isso acontecia apenas para um determinado registro apenas. Ou seja, não existia erro de programação porque para todos os demais registros da base a tal janela abria, somente para este não.  Não havia mensagem de erro, não havia depuração que pudesse identificar o problema, porque o fluxo de programa seguia normalmente em qualquer situação.

O que fazer nessa situação?

1. (  ) Destruir o computador com uma marreta de 3kg, e em seguida estourar o cartão de crétido para comprar um novo
2. (  ) Sair para tomar um sorvete e só voltar no mês seguinte
3. (  ) Ficar algumas horas colocando linhas de mensagens do tipo, 'passei por aqui', para tentar identificar a razão, e no final das contas não chegar a conclusão nenhuma.

Por obra do acaso, ao olhar a interface observei que havia uma variável, claro que não tinha nada a ver com a tal chamada (da interface com &window), que apresentava na interface um inocente valor -1, somente nessa situação.


Claro que coisa tão insignificante pode ser corrigida posteriormente, programador que se preze não perde tempo com besteiras... pois não precisamos interromper nosso raciocínio para corrigir algo tão estúpido, mesmo porque não podemos perder tempo.  E para piorar temos uma situação tão estranha que prioritariamente deve ser resolvida primeiro.

Enfim, resumindo, era isso e ao trocar -1 por zero na base de dados, o ceu passou a ser azul novamente.

Conclusão: gosto sempre de finalizar os posts com alguma mensagem otimista, e dessa vez a única que me vem a cabeça é: QUE ESTÚPIDEZ!

terça-feira, 21 de setembro de 2010

IN

Esse operador é uma daquelas boas invenções que o homem realizou até hoje, tal como a vacina contra gripe, o automóvel, a batatinha chips, a coca-cola, rs.... tirando os exageros, ele é legal mesmo, talvez você não tenha sido apresentado ainda, mas com certeza passará a observá-lo de forma melhor.

Seu objetivo é proporcionar a pesquisa ou acesso a uma coleção de dados, e está normalmente associado a um comando de repetição do tipo for ou for ... each. Meu objetivo aqui não é explicar muito a respeito de coleções, mas entenda o seguinte de forma simplificada, que consiste de uma variável do tipo conjunto de dados, algo similar aos vetores e matrizes, mas sem os limites de quantidades impostas por esses tipos.

Então considerando uma coleção qualquer, de nomes (imagem abaixo), poderíamos utilizar o operador IN para localizar qualquer um dos nomes da coleção em uma tabela de clientes, por exemplo.




Para isso precisaríamos programar algo bem simples como:








Para entender esse operador é simples, basta entender que a informação a ser localizada em (na) coleção localizada à esquerda.  Portanto ClienteNome será localizado (ou não) na &colecao e se isso ocorrer, o seu numero será apresentado.  A variavel  &colecao deve ser do tipo Char(20) marcada como collection. (revisado!)


Existem várias aplicações para isso, mostramos aqui como localizar conjuntos de dados de uma única vez utilizando uma variável coleção, mas é claro que você pode utilizá-lo para ligar, através de pesquisas, duas tabelas distintas desde que tenham alguma coisa em comum, e isso não quer dizer que tenham relacionamentos diretos ou indiretos.  Explicando um pouco melhor isso, um objeto Data Selector pode ser programado para realizar uma determinada consulta a uma tabela, e através do operador IN utilizar o resultado desta pesquisa para filtrar registros no for...each.



Mas isso é assunto para outra ocasião.

segunda-feira, 23 de agosto de 2010

O mistério da importação de Kb's

Após apanhar um pouco, mas também foi meio por estupidez, resolvi abrir o Output de mensagens, quando após várias tentativas a kb exportada de outro computador não conseguia ser aberta de jeito nenhum em uma nova máquina.  Estava tudo muito claro, eu é que não observei, alias estava destacado em vermelho indicando o erro, :(

O fato é que ao importar uma kb de um computador para outro, não se esqueça de instalar todos os controles (UC's) utilizados. A nova máquina deve ter instalada os mesmos controles utilizados na kb original, caso contrário o processo de importação é interrompido.

terça-feira, 3 de agosto de 2010

Apanhando do Tomcat

Essa não é a minha praia, portanto, não fiquem bravos comigo se eu escrever um monte de besteiras. Mas configurar o Tomcat com o Genexus é uma beleza!

Mesmo seguindos os passos a seguir, talvez tenha que reiniciar o Tomcat algumas vezes, e também fechar o Genexus para que todas as configurações 'peguem' corretamente.

Parte 1. Configuração das Propriedades do Genexus
Basicamente toda operação ocorre nas propriedades do environment (na KB) e na pasta do Tomcat, não sendo necessárioas configurações no sistema operacional.

1) Nome da aplicação Java:
  • Genexus definirá como nome da aplicação Java, no diretório do Tomcat, com a combinação entre o nome da KB e o nome do environment.
    Exemplo: KB=Teste, Environment=JavaEnvironment, o nome da aplicação será definida como: Teste.JavaEnvironment  
  • Um diretório será criado, pelo Genexus, no Tomcat para a publicação desta aplicação, na pasta webapps.
2) Diretórios Java:
  • Compiler Path: define o caminho para o compilador Java, que deve ser instalado através de um pacote Java Standard Edition, baixados da Sun.

    Compiler Path=C:\Program Files\Java\jdk1.6.0_20\bin\javac.exe
     
  • Interpreter Path: define o caminho para o interpretador Java, que deve ser instalado através de um Java Runtime Edition ou Java Standard Edition, baixados da Sun. A versão JSE é melhor para desenvolvimento porque já inclui o interpretador e compilador Java.

    Interpreter Path=C:\Program Files\Java\jdk1.6.0_20\bin\java.exe
     
  • Classpath: define os caminhos para os objetos de classe (jar, ou Java Archive) que são necessários para construir a aplicação. Normalmente é necessário indicar aqui as classes para acessar o Mysql e também a classe servlet-api.jar.  Ao criar o projeto já serão definidas alguns caminhos no Classpath, voce deverá incluir a parte que se encontra em negrito abaixo.

    classpath: gxclassr.jar;gxclassr.zip;GxUtils.jar;.;lucene-core-2.2.0.jar;iText.jar;./drivers/mysql-connector-java-5.1.13-bin.jar;./drivers/servlet-api.jar
     
  • Genexus já inclui um conector Java, mas é recomendado que baixe um mais recente e o copie na pasta drivers de sua aplicação.
  • Copie o arquivo C:\Program Files\Apache Software Foundation\Tomcat 6.0\lib\servlet-api.jar na pasta drivers de sua aplicação. No final a pasta drivers deve ficar com a seguintes classes:

3) Diretório e caminhos para o Tomcat:
  • Servlet Directory: é o diretório onde roda a aplicação Genexus + Java no Tomcat. Na propriedade deverá ser indicado o caminho até a pasta classes.

    Servlet Directory=C:\Program Files\Apache Software Foundation\Tomcat 6.0\webapps\Teste.JavaEnvironment\WEB-INF\classes
     
  • Static Directory: é o diretório onde o Genexus armazenará as informações estáticas (imagens, arquivos js, ...) da aplicação

    Static Directory=C:\Program Files\Apache Software Foundation\Tomcat 6.0\webapps\Teste.JavaEnvironment\static
     
  • Web Root: indica a URL que será chamada pelo cliente para rodar a aplicação. No ambiente de teste deverá ser o próprio nome do projeto (item 1).

    Web Root=http://localhost:8080/Teste.JavaEnvironment/servlet/
     
  • Referente ao numero 8080, representa a porta ativa do Tomcat no servidor, caso queira o padrão, (80), e desde que não tenha o IIS instalado na mesma máquina, poderá alterar a configuração do arquivo C:\Program Files\Apache Software Foundation\Tomcat 6.0\conf\config.xml.
Parte 2. Configuração do Tomcat
Aqui a coisa pega um pouco porque depende muito de instalação para instalação, vou reproduzir as configurações que fiz nessa kb de teste.

Primeiramente desligue o Tomcat e faça uma cópia dos arquivos que estão sendo reconfigurados, por segurança.

1) Configuração do web.xml
  • O web.xml é um arquivo de configuração que se encontra no diretório C:\Program Files\Apache Software Foundation\Tomcat 6.0\conf.
  • Minha configuração ligou as propriedades invoker que estavam anteriormente marcadas com comentário.
  • E também no servlet-mapping:
2) Configuração do Catalina:
  • Na pasta C:\Program Files\Apache Software Foundation\Tomcat 6.0\conf\Catalina\localhost, crie um arquivo chamado Teste.JavaEnvironment.xml.
  • Com o seguinte conteúdo:

3) Pasta lib:
  • Reproduza (copie) o conteúdo da pasta drivers (da aplicação) na pasta lib (do Tomcat), que se encontra no diretório C:\Program Files\Apache Software Foundation\Tomcat 6.0\webapps\Teste.JavaEnvironment\WEB-INF


Importante: nesse modelo de configuração (via invoker) não crie nenhum arquivo web.xml na pasta WEB-INF, senão não funcionará.

Finalmente, ligue o Tomcat e execute a aplicação. 'Acho' que conseguirá rodar de primeira, mas ai é outra história.

segunda-feira, 19 de julho de 2010

Rompendo relações implícitas!

Genexus é uma ferramenta tão poderosa que as vezes precisamos desligá-la, isso pra fazer algo de forma mais 'estúpida'. Estou falando a respeito da capacidade da ferramenta em encontrar relações entre tabelas dentro do modelo da base de dados.

A regra é que quando programamos for...eachs aninhados (um dentro do outro) a ferramenta sempre tentará encontrar a relação entre duas tabelas, e para isso buscará encontrar a relação no conjunto de tabelas estendidas. Isso é o que se chama relação implícita, e se o Genexus encontrar a tal relação, o programador não precisa programar cláusulas where para conectar as duas tabelas.

Vamos estudar um modelinho.



Por exemplo, se queremos relacionar a tabela B com a tabela D, o que existe em comum entre as duas é a tabela C, e o atributo c*, desta forma se programarmos dois for...eachs aninhados, conforme abaixo, teríamos:

A relação implícita existente entre os dois for...eachs será o que existe em comum entre as duas tabelas, que corresponde ao atributo (c*).

A questão que colocamos é como desligar essa maquininha de relações implícitas do Genexus, digamos para fazer algo como relacionar manualmente B com C, B com E, ou mesmo F com A, isto em situações diferentes de c=@c.?

Existem várias práticas que poderiam ser aplicadas, e como queremos fazer algo 'estúpido', podemos substituir os for...eachs aninhados por for..eachs paralelos. Claro que ao fazer isso estamos quebrando todas as relações existentes.  E não me pergunte a respeito de desempenho, por favor.

Tente uma subrotina.



Fazer algo assim tão anti-natural em Genexus pode auxiliar em algum problema mais prático, principalmente causado por projetos complexos de projeto de bases de dados, e relações não tão implícitas assim.  Mas não se esqueça que Genexus quase sempre tem sempre razão no quesito database, e a solução dele sempre será a mais eficiente.

sexta-feira, 9 de julho de 2010

Melhorando o tempo de expiração da sessão

Uma das dificuldades enfrentadas pelos usuários em sistemas WEB é o fato de que, antes de completar um formulário, com muitos dados, complexo, chato,  o tempo de sessão expira antes do pressionamento do botão confirmar. Já viu isso? eu já

O ASP.NET utiliza o arquivo web.config para configurar a aplicação web, existindo diversos parâmetros que podem ser controlados. Nosso interesse nesse instante é apenas no tempo de expiração da sessão.

Utilizo o exemplo abaixo para estabelecer um tempo de expiração de 2000 segundos, de inatividade do usuário.



Os parametros significam:

  • Mode.  inproc, que significa que o estado da sessão é gerenciada como um processo no servidor, e qualquer se o processo é desligado o estado é perdido, em outras palavras, se você desligar o servidor por um curto periodo de tempos as sessões serão todas desligadas
  • Cookieless. é um parâmetro booleano e significa que não será gravado cookie na máquina do cliente.
  • Timeout. esta opção determina o tempo em que uma sessão será considerada válida a partir de uma determinada chamada, ou seja, considera-se o horário da chamada + o tempo definido nesse parâmetro para que a sessão seja fechada automaticamente.  A cada chamada do usuário ativo fará com que o contator seja zerado novamente.
Para maiores informações melhor consultar a fonte: http://msdn.microsoft.com/en-us/library/ms972429.aspx

quarta-feira, 7 de julho de 2010

Mais uma pra coleção: GXM_badnum

Mais uma pra minha coleção de coisas esquisitas! GXM_BADNUM. Já viu isso?

Situaçãozinha estranha, erro aparecendo em um local onde nunca havia aparecido antes. E em outro lugar, também com a entrada numérica.  Nesse outro local o erro aparecia com uma mensagem: The value is not a valid number.


Passado o pânico inicial que segue algo tão estranho, me recordo que criei a kb recentemente, e importei os objetos do programa para essa kb nova, e algo me diz para verificar o idioma da aplicação.

Batata! kb criada originalmente em Inglês e quando se informa um valor 2.00 o resultado é um belo valor 200.00, ou seja, está acontecendo erro na conversão de , para . e vice-versa.

Solução: colocar Translation type=Static, e Translate to language=Portuguese, Build all e pronto, já era.

terça-feira, 6 de julho de 2010

O perigo de ter duas mulheres!

Esse assunto é tão delicado que até o título é perigoso. Nunca aconteceu comigo, mas já vi esse filme várias vezes. E acho que você também. Faz parte do quotidiano da raça. Algo do tipo chamar a Jane de Francisca é algo inconcebível no relacionamento, e aí é que mora o perigo. Tão grande que pode causar até o pior...

Imaginemos então uma situação diferente, um sorteio através de uma lista de nomes, alguns homônimos, tipo José da Silva, José da Silva, José da Silva,..., e mais alguns Josés da Silva. No momento do sorteio, se sair José da Silva, complicou a vida.

GeneXus também tem um problema quando se trata de coisas iguais na interface, e olha que nem é culpa dele, a tecnologia web tem dessas coisas. E da mesma forma que acontece nos ‘causos’ citados anteriormente, aqui também a coisa pega.

Por exemplo, se você colocar um ClienteId e ClienteNome no Grid1, claro que o ClienteId não precisa ser apresentado, pode ficar oculto, e no Grid2 que trata das compras do Cliente, colocamos ClienteId, CompraData, CompraValor, e por algum acaso da necessidade, deverá se expandir o registro de compras, ... , poderemos estar chamando a Jane de Francisca.

Acontece que existem dois ClienteId’s em dois grids distintos, que poderão possuir valores distintos também, nunca se sabe. Por exemplo, o primeiro Grid1 mostra todos os clientes, e o Grid2 mostra as compras que ainda não foram pagas por todos os clientes. Ou seja, os grids podem operar de forma desassociada um do outro.

Daí meu amigo, é crime! Como referenciar uma operação de expansão de um registro do Grid2, se você não controla o valor de ClienteId?

Confuso? Isso é o que dá duas mulheres ao mesmo tempo, confusão, então simplifique, nunca coloque na mesma interface atributos ou variáveis iguais, senão estará casando com duas mulheres, ou mais, ...

quinta-feira, 1 de julho de 2010

Boas maneiras!

Quando você era criancinha sua mamãe e papai lhes ensinaram uma série de 'boas maneiras', e talvez a que mais fixou em seu cérebro foi: NÃO FALE PALAVRÕES. Pois é esse ai guardamos por toda vida.

Genexus e C# também nos ensinam boas maneiras, principalmente referentes aos 'palavrões' não aceitos.  Tive uma aula de boas maneiras ontem, até que bem interessante, e tirei algumas boas conclusões, que compartilho com vocês.

Boas Maneiras 1) Como dar Nó na Gravata:

O nó que tive que resolver foi o seguinte, programando uma SDT simples, com algumas informações referentes a emails, como destinatário, título, mensagem, essas coisas, e tive a brilhante idéia de programar tudo em inglês (mania).

O resultado foi um belo STD com a seguinte forma:


Fala sério, ficou até bonitinho hein. Mas acontece que por causa desse lindo SDT foram horas de canseira, e não havia jeito de entender o erro de compilação do C#.

Conclusão:  Nunca utilize palavras reservadas ou tipos pré-definidos em SDT's, tais como TO, MESSAGE,..., e veja que usei várias em um mesmo local, isso é que foi falta de educação.

Dai fica simples dar o nó, basta entrelaçar as coisas corretamente.

Boas Maneiras 2) Não cometa extravâgancias

Esse aqui também mamãe lembrava sempre, mas não teve jeito, de vez em quando acontece. E a minha extravagância foi também cometida no mesmo SDT anterior.

Pensa comigo:  C# é escrito em inglês, Gx é escrito em inglês, ..., então a probabilidade de cometer um erro tosco desse é escrever variáveis, elementos de SDT, DP, em ...inglês.

Pois é, minha mania custou caro, e minha recomendação aqui é: se for cometer uma extravagância dessas não dirija, em outra palavra: CAUTELA.

sábado, 26 de junho de 2010

Method not found: 'GeneXus.WebControls.GXWebRow GeneXus.WebControls.GXWebRow.GetNew(GeneXus.Application.IGxContext, Int32)'.

Comecei a colecionar mensagens legais geradas pelo Gx+ASP.NET, essa ai é mais uma que apareceu onde não deveria.    E sabe o que ela significa?
Pra mim significou, volte a versão do Upgrade 2.5 para o Upgrade 2 do Gx, que tudo volta ao normal.

segunda-feira, 21 de junho de 2010

Genexus Mail! versão em código nativo

Genexus possui todos os recursos necessários para a operação de envio de email, portanto, não leia essa postagem.  A não ser que você se sinta mais a vontade programando nativamente em C#, mas lembre-se: ao fazer isso você cria kbs restritas a esse único ambiente, situação altamente não recomendada.

Se mesmo com essa recomendação, você insistir, então nesse caso temos algumas boas possibilidades e a primeira é escrevendo diretamente usando CSHARP, para isso segue o código abaixo.


Lembre-se que as variáveis Genexus são sempre marcadas com [!&variavel...!].  O código retornado &statusEnvio é marcado com 1 se o email foi enviado com sucesso.

É necessário definir os valores para as variáveis de configuração, que testamos em um email qualquer.

E as variáveis foram definidas com:
Simples, e o mais interessante é que esse código nativo encontra-se amplamente divulgado na Web, ou seja, não é nossa criação.

O mais importante é que funciona perfeitamente, e rápido.

sábado, 12 de junho de 2010

Genexus Mail!

Esse é um dos tópicos bem divulgados na comunidade, mas boas características devem sempre ser exaltadas.  E uma delas é a capacidade de Genexus implementar a programação com mínimos recursos.

Um bom exemplo disso é o envio de email por meio do tipo SendMail.

Para testar esse recurso, você não precisa muita coisa, a não ser seguir os passos do código fonte abaixo:
Lembrando que as variáveis de configuração apenas definem os dados necessários para o servidor SMTP, que podemos simplificar da seguinte forma:

Host: smtp.servidor.com.....
User: user@servidor.com....
Password: *****
SenderEmail: user@servidor.com...
SenderName: Email de Teste

Com as variáveis definidas como:

Simples e fácil, boa sorte.

segunda-feira, 31 de maio de 2010

Colecionando Figurinhas!

Interessante como temos mania de colecionar coisas, veja o momento, agora todo mundo está colecionando as figurinhas da copa do mundo, e tem até bandido roubando a carga das tais figurinhas, e vendendo por um precinho mais 'camarada' no mercado negro!. Coleções de selos, coleções de insetos, ..., e  ai vai.

Genexus também possui coleções, e o interessante desse recurso é que, assim como acontece no mundo real, as coleções normalmente se constituem de conjuntos de dados cuja dimensão não é conhecida. Diferentemente de seus primos próximos, e limitado, que são as matrizes e vetores.

Então para ficar bem claro, as coleções em Genexus são elementos criados a partir de variáveis, que são, portanto, armazenadas na memória do servidor web (claro, em sistemas web) e que permitem a realização de operações sobre conjuntos.

Para clarear ainda mais as idéias, vai ai um exemplo.  Um painel, com um grid obtém seus dados a partir da chamada a um procedimento que devolve a coleção a ser carregada. No Source do procedimento temos:

&item = "Itapecerica da Serra"
&lista.Add(&item)

&item = "Mombuca"
&lista.Add(&item)

&item = "Divinópolis"
&lista.Add(&item)

Sendo &item uma variável simples do tipo Character(20) e &lista uma variável do tipo Character(20) marcada como Collection. Na regra PARM deste procedimento temos:

parm(out:&lista);

A chamada ao procedimento ocorre no evento Start de um WebPanel, que possui um Grid com uma variável &cidade (Character 20), que é carregada com os dados da lista obtida.

Event Start

   &lista = Procedure1.Udp()
   for &item in &lista
      &cidade = &item
      load
   endfor
EndEvent

E claro que o resultado não podia ser outro.







E por falar em figurinha, tenho algumas repetidas aqui comigo e está faltando na minha coleção a do Luiz Fabiano, alguem tem ai?


  

sexta-feira, 7 de maio de 2010

Kung fu dos textos!

Você deve estar imaginando que raio de titulo é esse! Isso porque você não deve ter muita intimidade com o SplitRegEx, caso contrário o acharia até normal. Diante desse faixa preta, não existe oponente, ele quebra mesmo!

O SplitRegEx é uma função que opera sob a forma de expressão regular que tem por finalidade quebrar um texto do tipo CHARACTER, ele não aceita varchar ou longvarchar, em partes que  normalmente armazenadas em uma Collection. A regra para a quebra é definida por uma expressão que pode ser um ou mais caracteres que simbolizam a separação entre as partes de texto.

Por exemplo, arquivos CSV, separa as partes de um texto por meio de ponto-e-virgula ou qualquer outro caracter. Desta forma a frase a seguir tem um significado de um conjunto de informações separadas pelo mesmo texto.

10;Jose da Silva; Av.Central,10;Santana do Parnaiba;São Paulo

Desta forma essa função é muito útil na sua luta diária com Genexus. E para definir o tatame voce pode criar um WebPanel. E na área de Events programe:

Event Start
     &texto  = "10;Jose da Silva; Av.Central,10;Santana do Parnaiba;São Paulo"
     &itens   =  &teste.SplitRegEx(';')
     for &item in &itens   
             msg(&item)
     endfor
EndEvent

As variáveis podem ser definidas como:

&item  = Character(100)
&itens  = Character(100) - Collection
&texto = Character(200)

O resultado é a quebra do texto nas partes indicadas por ; e a apresentação de cada parte individualmente como uma mensagem.

Observe que em &itens voce terá uma série de informações, tais como o numero de itens, o item corrente navegado, entre outros.

Boa luta!

segunda-feira, 3 de maio de 2010

Para os fãs de csharp

A grande pergunta é como referenciar uma classe da biblioteca .NET C#, ou outra fornecida por terceiros, dentro de um código diretamente escrito com csharp, visto que não existe a opção de usar o import. Isso ocorre porque ao incluir csharp você está programando um método, não uma classe, e está no meio do programa fonte, e claro, a documentação sobre esse assunto é escasso em GeneXus, visto que esse conceito foge totalmente da filosofia GeneXus de gerar produtos em diversas linguagens a partir de uma única KB.

Mas na prática, de vez em quando, e em casos muito específicos, temos que recorrer a esse recurso, mas nunca é demais recomendar cautela ao usá-lo. Opte sempre em usar o External Object, se estiver no GeneXus X ou EV. Se você precisa utilizar muito esse recurso em programa GeneXus, com certeza não está no caminho correto.

Para os corajosos, então ai vai! primeiramente deve-se instalar a DLL na pasta BIN da aplicação, por exemplo, algo como a classe IBM.Data.DB2.iSeries.dll, para conexão no DB2.

Em seguida a opção para incluir a classe no projeto, para isso utilizar o recurso de inclusão via compilador C#. Para isso Nas preferências do projeto voce encontrará a opção Compiler Flags, que deverá conter /lib:bin  /r:IBM.Data.DB2.iSeries.dll.  Esse recurso indica a pasta lib e o nome da referência que será adicionada pelo compilador.

Agora fica fácil! brincadeirinha... É programar em csharp, referenciando as classes com o nome da DLL, como a seguir:


        csharp  using (IBM.Data.DB2.iSeries.DB2Connection myConnection = new IBM.Data.DB2.iSeries.DB2Connection(myConnString))
        csharp  {
        csharp      IBM.Data.DB2.iSeries.DB2Command myCommand = new IBM.Data.DB2.iSeries.DB2Command(mySelectQuery, myConnection);
        csharp         myConnection.Open();   
        csharp        IBM.Data.DB2.iSeries.DB2DataReader myReader = myCommand.ExecuteReader();
        csharp         while (myReader.Read())
        csharp        {
        csharp         ...
        csharp       }
        csharp       myReader.Close();
        csharp       myConnection.Close();
        csharp  }
Agora é só adaptar pra sua necessidade.

domingo, 2 de maio de 2010

Cosinhas legaizinhas no SQL Server

Descobri que mesmo para um desenvolvedor Genexus, Java, NET, ... é necessário conhecer macetes a respeito de todo ambiente onde sua aplicação está rodando, isso te ajudará a sair de certos incêndios.

Em ambientes corporativos as tarefas são normalmente designadas para pessoas diferentes, devendo ocorrer o contato/solicitação para que alguma situação em sua área seja resolvida por um gênio de outra área, levando a muita especialização em um único assunto.

Um bom desenvolvedor Genexus consegue conciliar o conhecimento profundo na ferramenta com o essencial para sobreviver no ambiente em que a aplicação está executando (compilador, linguagem, banco de dados,  servidor web, ....,  ), já um desenvolvedor Genexus eficiente e flexível busca conhecer muito sobre o entorno da aplicação, pois sabe que isso o levará a criação de sistemas muito mais eficientes, com utilização de todos os recursos que a tecnologia oferece.

Aviso! Não tenho tido muito tempo para me aprofundar no Microsoft SQL Sever, e se esse for seu caso, por favor não continue a ler este blog, pois me achará meio ignorante nisso, o que é pura verdade!.

Então, para os que estão começando a compreender o SQL Sever, como eu, vamos lá!

Como copiar todos os dados de uma tabela em outra, mas em bancos diferentes
Essa pode te salvar quando é necessário dar um Create Database no Genexus, e voce não pode perder dados que se encontram em uma determinada base de dados. Nesse caso voce pode criar uma nova database para a aplicação, mantendo a antiga intacta e em seguida realizar a operação de carga da antiga para a nova.

INSERT INTO tabela_destino     SELECT  * FROM  db_fonte..tabela_fonte

Nesse caso a estrutura (ordem e numero de atributos) da tabela_destino deve ser a mesma da tabela_fonte, e observe que a query está rodando a partir da database_destino.

Como copiar alguns atributos de uma tabela em outra, mas em bancos diferentes
Essa pode te salvar quando ocorreu mudança estrutural entre a tabela_destino e a  tabela_fonte, mas a fonte possui a maioria da informação que voce necessita para carregar 'inicialmente' a tabela_destino.

INSERT INTO tabela_destino  (atr1, atr2, atr3)   SELECT  atr1, atr2, atr3 FROM  db_fonte..tabela_fonte

Nesse caso a ordem dos atributos da tabela_destino deve ser a mesma da lista selecionada na tabela_fonte, e observe que também a query está rodando a partir da database_destino.

Como copiar desligando o identity
Quando ocorre mudança estrutural entre a tabela_destino e a  tabela_fonte, é possível copiar parte da informação, mas o problema é sincronizar os valores das chaves numéricas que foram definidas como Autonumber=yes, ou seja, com Identity=Yes.

SET IDENTITY_INSERT tabela_destino ON
INSERT INTO tabela_destino  (atr1, atr2, atr3)   SELECT  atr1, atr2, atr3 FROM  db_fonte..tabela_fonte
SET IDENTITY_INSERT tabela_destino OFF

Nesse caso a ordem dos atributos da tabela_destino deve ser a mesma da lista selecionada na tabela_fonte, e observe que também a query está rodando a partir da database_destino. O atributo atr1 é chave e é normalmente designado como IDENTITY=YES.


Alterar valor do contador IDENTITY
Para posicionar o contador do autonumber para um valor especifico execute:
DBCC CHECKIDENT('tabela_destino', RESEED,


Agradeça ao meu amigo Claudio Shinji, pela ajuda nesse blog, ok!



Genexus lento - Parte II

Parece meio estranho, mas muito dinamismo é ruim pra caramba, e isso é o que o AVAST tem dito pra todo desenvolvedor, ou seja, se você carregar seu programa com muita coisa, pode deixar que eu vasculho tudo a cada GET ou POST no servidor, mesmo aqueles arquivos que eu já testei (nessa sessão), e sabe o que mais, vou deixar seu programa tão lento de forma que voce terá que ler o blog para descobrir como me desligar.

É isso mesmo que o AVAST, na sua versão mais recente, está fazendo no seu inocente e puro sistema criado com Genexus, vasculhando tudo, sem dó, parece coisa de filme policial americano, ou mesmo do 'nosso' Capitão Nascimento tupiniquim.

E como desligar esse 'vilão' para que deixe nosso programinha em paz?

1. Abrir o Avast
2. Abrir Módulos Residentes
3. Pressionar configurações avançadas
4. Selecionar Exclusões
5. Pressionar Acrescentar

Inclua ai as regras para acesso ao seu sistema apenas, senão o antivirus irá desconsiderar toda navegação na web. Para isso é necessário voce colocar o nome do diretório virtual antes da regra.

Por exemplo:

*\vs1\*.aspx
*\vs1\*.css
*\vs1\*.jpg
*\vs1\*.png
*\vs1\*.js

E assim por diante, lembrando que antes do *\vs1\ voce tem a sua URL, que não precisa ser inserida na regra (opcional).

É isso! espero que o próximo não seja um triller de terror!

www.localhost.com

Tenho sido surpreendido pelo IIS estar direcionando as chamadas http://localhost para http://www.localhost.com, e isso permanece em qualquer browser, pois tenho todos instalados. Tenho também o Tomcat, e ambos rodavam bem, antes do causo, claro, desde que um não bata na porta do outro.

Pouca informação na web sobre isso, a maioria trata de problemas no ipv6, mas no meu ponto de vista é virus (ou coisas do genero), e dá um certo trabalho pois nenhum anti-virus consegue descobrir a coisa.

Passos:
1. Em C:\Windows\System32\drivers\etc tem um arquivo chamado Hosts.
2. Remova desse arquivo a linha ::1 ...
3. Reinicie a máquina

Aqui funcionou, espero que ai também.