Esse é um tópico que irá mostrar algo que definitivamente você já precisou mas não sabia como fazer e que facilitará (e muito) alguns trabalhos. Programadores que usam o Bando de Dados para programar sendo por Stored Procedure, Functions e Triggers já passaram por maus bocados para preparar um algoritmo que realizasse um determinado processo, mas que esse mesmo algoritmo é mais fácil de ser escrito (ou possuir funcionalidades que o SGDB não possui) em outra linguagem de programação. Por exemplo: validar e-mail. É possível no SQL Server fazermos um Function que receba um VARCHAR e retorne um BIT informando que um e-mail é válido ou não, contudo seria uma função um tanto que trabalhosa para quem não está familiarizado com programação em banco. Para quem desenvolve em ASP.NET (C# ou VB.NET) basta usarmos expressão regular que, em duas linhas, resolve o problema. Portanto iremos utilizar uma função escrita em C# compilada em uma DLL e usarmos em um Function no SQL Server. Isso é possível através do CLR.
Primeiramente vamos criar a DLL contendo a função (no nosso exemplo vamos fazer a que valida e-mail - mas você pode desenvolver a que quiser). Abra o Visual Studio e crie um Project. Em Project Type escolha Visual C# Windows e o Template opte por uma Class Libary. Note que quando você cria uma classe vem com o nome Class1.cs. Para facilitar a compreensão, renomeie para FuncoesSql.cs (ou outra) e remova o namespace criado. Agora, escreva a função que deseja e adicione os namespaces necessários ficando da seguinte forma:
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.SqlServer.Server;
public partial class FuncoesSql
{
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlBoolean IsMailValido(SqlString email)
{
// Cria um objeto de expressões regulares para validar e-mail
Regex expressaoRegular = new Regex(@"^(([^<>()[\]\\.,;:\s@\""]+"
+ @"(\.[^<>()[\]\\.,;:\s@\""]+)*)(\"".+\""))@"
+ @"((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"
+ @"\.[0-9]{1,3}\])(([a-zA-Z\-0-9]+\.)+"
+ @"[a-zA-Z]{2,}))$");
// Realiza um teste na validação da expressão
return new SqlBoolean(expressaoRegular.IsMatch(email.ToString()));
}
}
No caso, precisamos explicitar os tipos de entrada e saída utilizados pelo banco de dados para que não haja problemas de tipagem. Poderia ser qualquer função ou quantas que quisesse, contanto que respeite os tipos. Agora compile a DLL pressionando F6 ou pelo menu Build. Já temos a DLL com a função. Copie a DLL (que está na pasta bin\Debug de sua solução) e coloque-a em um local onde seu Banco de Dados possa buscá-la. Para exemplo, colocarei em C:\SqlDlls\ no Servidor.
O próximo passo é verificar se no SQL Server está ativo a funcionalidade CLR, para isso vá em Iniciar > Todos os Programas > Microsft SQL Server 2008 (ou 2005) > Configuration Tools > SQL Server Surface Area Configuration. Entre em Surface Area Configuration for Features e na guia CLR Integration verifique se a função está habilitada. Se não estiver, habilite.
Dê OK e agora já poderá usar CLR no SQL Server. Abra o SQL Server Management Studio, conecte-se na base desejada e execute as seguintes instruções SQL (abra um New Query para isso):
-- CRIA O ASSEMBLY INDICANDO SUA ORIGEM
CREATE ASSEMBLY FuncoesSql FROM 'C:\SqlDlls\FuncoesSqlServerASPNET.dll'
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- CRIA A FUNÇÃO
CREATE FUNCTION dbo.Fun_Valida_Mail (@email NVARCHAR(350))
RETURNS BIT
-- INDICA A ORIGEM DA FUNÇÃO SQL: ASSEMBLY > CLASSE > FUNÇÃO
AS EXTERNAL NAME [FuncoesSql].FuncoesSql.IsMailValido
GO
Agora execute a Query (ou pressione F5)... Foi criada a função! Pronto... agora é só usar como se fosse uam função do SQL Server normalmente. Abaixo tem alguns exemplos de consulta e seus retornos:
Execuções:
SELECT dbo.Fun_Valida_Mail('tmarcal@gmail')
SELECT dbo.Fun_Valida_Mail('tmarcal@gmail.com')
SELECT dbo.Fun_Valida_Mail('tmarcal.. @gmail.com')
Retorno:
0
1
0
Apesar do trabalho inicial, pode-se aproveitar muito de ambos os recursos e criar cada vez mais funções complexas. Quanto ao desempenho da CLR, em comparação ao T-SQL, deve-se ficar a mesma coisa. A diferença é praticamente imperceptível. Espero que tenham gostado... Até breve!
Utilizando função de uma DLL Externa no SQL Server
Postado por
Thiago Marçal
on sábado, 21 de agosto de 2010
/
Marcadores:
clr,
dicas,
dll,
sql server,
visual studio
/
Comments: (4)
Não foi possível carregar arquivo ou assembly System.Web.Extensions, Version=2.0.0.0
Postado por
Thiago Marçal
on quarta-feira, 18 de agosto de 2010
/
Marcadores:
crystal reports,
dicas,
dll
/
Comments: (29)
Dica rápida para quem tiver esse erro...
Acontece quando está utilizando uma versão do ASP.NET Ajax diferente do Framework da aplicação. Muitas vezes, também, acontece quando está utilizando o Crystal Report ao renderizar um relatório. Então é exibido a seguinte mensagem:
A solução é simples: basta remover a System.Web.Extensions.dll e/ou System.Web.Extensions.Design.dll do projeto (na pasta Bin).
Acontece quando está utilizando uma versão do ASP.NET Ajax diferente do Framework da aplicação. Muitas vezes, também, acontece quando está utilizando o Crystal Report ao renderizar um relatório. Então é exibido a seguinte mensagem:
A solução é simples: basta remover a System.Web.Extensions.dll e/ou System.Web.Extensions.Design.dll do projeto (na pasta Bin).
Não foi possível carregar arquivo ou assembly 'System.Web.Extensions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' ou uma de suas dependências. A definição do manifesto do assembly localizado não corresponde à referência do assembly. (Exceção de HRESULT: 0x80131040)
Dicas de Instruções SQL para facilitar o uso no dia-a-dia
Postado por
Thiago Marçal
on domingo, 15 de agosto de 2010
/
Marcadores:
dicas,
sql server
/
Comments: (0)
Bom, abaixo separei algumas instruções SQL que muitos programadores tem dúvidas de como usá-las e que facilitam muitas tarefas.
1) INSERT de SELECT: Fazer inserções em uma tabela puxando dados de outra(s)
Bem parecido com o SELECT INTO porém você pode fazer várias manipulações conforme desejar usando um simples SELECT. No caso vou mostrar um exemplo bem fácil: irei adicionar vários Alunos numa tabela sendo que os dados estão em outra tabela (Cadastros), logo minha instrução ficaria assim:
INSERT INTO Alunos (nome, email) SELECT nome, email FROM Cadastros
O nome dos campos não precisam serem iguais, basta estar na mesma ordem e respeitar o tipo de dados (tamanho também).
2) UPDATE relacionado com outra tabela
Nessa situação o que desejamos é fazer um UPDATE na tabela sendo que é preciso fazer um JOIN com outra tabela. No nosso exemplo: desejamos alterar o preco de um produto sendo que o valor do mesmo está relacionado com seu tipo e ele está armazenado em outra tabela. Logo podemos usar a seguinte instrução:
UPDATE Produto SET preco = T.preco FROM Produto AS P, Tipo AS T WHERE P.Id_Tipo = T.Id
Meio complicado quando se vê, né? Mas se você reparar detalhadamente verá que a atualização do preço é feita, para cada produto, quando o Id_Tipo (da tabela Produto) for igual ao Id (da tabela Tipo) obtendo assim o preco (da tabela Tipo).
3) Remover registros duplicados deixando apenas um
A explicação desse objetivo é bem óbvia: remover registros duplicados em uma determinada tabela sob,algum critério. Porém, sua sintaxe é mais complicada, mas vamos lá... Para nosso exemplo iremos remover os registros duplicados (ou mais que um) de e-mails deixando apenas um na tabela Mailing:
;WITH Listagem(email, ranking)
AS
(
SELECT email
,ranking = DENSE_RANK() OVER(PARTITION BY email ORDER BY NEWID() ASC)
FROM Mailing WITH (NOLOCK) WHERE email IS NOT NULL
)
DELETE Listagem WHERE ranking > 1
Esse emaranhado de instruções se resume em gerar um ranking indicando quantas vezes o registro se repete. Esse ranking é armazenado em uma tabela "temporária" (tabela Listagem) com referência à original (tabela Mailing)... Logo que é gerado o ranking, é feita a exclusão dos registros que possuem ranking maior que 1, ou seja, apaga todos aqueles que estão se repetindo deixando apenas um deles.
Bem, é isso! Espero ter ajudado... Lembrando que os exemplos acima foram os mais simples e vocês podem encontrar situações semelhantes ou piores mas que, usando-os, podem ajudar a chegar na resolução.
1) INSERT de SELECT: Fazer inserções em uma tabela puxando dados de outra(s)
Bem parecido com o SELECT INTO porém você pode fazer várias manipulações conforme desejar usando um simples SELECT. No caso vou mostrar um exemplo bem fácil: irei adicionar vários Alunos numa tabela sendo que os dados estão em outra tabela (Cadastros), logo minha instrução ficaria assim:
INSERT INTO Alunos (nome, email) SELECT nome, email FROM Cadastros
O nome dos campos não precisam serem iguais, basta estar na mesma ordem e respeitar o tipo de dados (tamanho também).
2) UPDATE relacionado com outra tabela
Nessa situação o que desejamos é fazer um UPDATE na tabela sendo que é preciso fazer um JOIN com outra tabela. No nosso exemplo: desejamos alterar o preco de um produto sendo que o valor do mesmo está relacionado com seu tipo e ele está armazenado em outra tabela. Logo podemos usar a seguinte instrução:
UPDATE Produto SET preco = T.preco FROM Produto AS P, Tipo AS T WHERE P.Id_Tipo = T.Id
Meio complicado quando se vê, né? Mas se você reparar detalhadamente verá que a atualização do preço é feita, para cada produto, quando o Id_Tipo (da tabela Produto) for igual ao Id (da tabela Tipo) obtendo assim o preco (da tabela Tipo).
3) Remover registros duplicados deixando apenas um
A explicação desse objetivo é bem óbvia: remover registros duplicados em uma determinada tabela sob,algum critério. Porém, sua sintaxe é mais complicada, mas vamos lá... Para nosso exemplo iremos remover os registros duplicados (ou mais que um) de e-mails deixando apenas um na tabela Mailing:
;WITH Listagem(email, ranking)
AS
(
SELECT email
,ranking = DENSE_RANK() OVER(PARTITION BY email ORDER BY NEWID() ASC)
FROM Mailing WITH (NOLOCK) WHERE email IS NOT NULL
)
DELETE Listagem WHERE ranking > 1
Esse emaranhado de instruções se resume em gerar um ranking indicando quantas vezes o registro se repete. Esse ranking é armazenado em uma tabela "temporária" (tabela Listagem) com referência à original (tabela Mailing)... Logo que é gerado o ranking, é feita a exclusão dos registros que possuem ranking maior que 1, ou seja, apaga todos aqueles que estão se repetindo deixando apenas um deles.
Bem, é isso! Espero ter ajudado... Lembrando que os exemplos acima foram os mais simples e vocês podem encontrar situações semelhantes ou piores mas que, usando-os, podem ajudar a chegar na resolução.
Problema do Mootools dentro de um frame
O Mootools é um framework JavaScript para criar abas com um belo design e praticidade no uso. Porém verifiquei que ele tem um certo "probleminha de comportamento" quando o usa dentro de um frame / frameset no IE. O seu carregamento / aplicação de estilo se dá através de uma adição de uma função chamadora na janela (usando window.addEvent). A condição para execução do script se dá quando o DOM estiver pronto, ou seja, window.addEvent('domready',function({})); . O problema é que, para o Internet Explorer (IE) o carregamento da página é meio que desordenado enquanto o Firefox e Chrome (não testei nos demais navegadores) possuem uma ótima engine de carregamento de página. Ou seja, à vezes o conteúdo da página demora a ser carregado e o DOM fica pronto antes dos controles HTML serem devidamente carregados ocasionando erro na execução. Para contornar o problema, basta substituir o 'domready' por 'load'. Então a aplicação do Mootools sobre o conteúdo será providenciado logo que a página for totalmente carregada. O problema é se houver muito conteúdo na página e houver demora no carregamento da página pois o estilo será aplicado apenas no final... daí é só ter mesmo paciência (ou remove do frame)!
Obs: outros frameworks JavaScript podem vir a ocasionar o mesmo problema sob as mesmas circunstâncias.
Obs: outros frameworks JavaScript podem vir a ocasionar o mesmo problema sob as mesmas circunstâncias.
Problema no uso de memória no SQL Server 2008
Se em algum momento, quando em trabalho, estiver recebendo uma das seguintes mensagens abaixo, você está tendo sérios problemas de uso de memória:
Isso ocorre quando há várias instruções SQL sendo executadas em seqüência. Como o pool não aguenta, os dados, em algumas vezes, podem travar... Mesmo que fisicamente eles estejam lá, não se pode mais ser utilizados até que o banco seja reiniciado. Para corrigir esse problema há duas formas: instalar o hotfix que a Microsoft disponibilizou ou reduzir quantidade de instruções a serem executadas por vez.
1) Instalar o HotFix
O arquivo está disponível em um pack cumulativo pós SP1 do SQL Server 2008. Para mais informações e download, clique aqui.
2) Reduzir a quantidade de instruções SQL
Fazendo um teste de vários UPDATE's seguidos, consegui obter tal erro. Gerei um arquivo .sql com quase 100mil updates e mandei o SQL Server executar, daí obtive o erro. Nunca tente isso! Se desejar executar vários UPDATE's ou INSERT's de vez fragmente a execução das instruções em blocos (nem tão grandes e nem tão pequenos) dando uma pausa entre as execuções. Pode-se utilizar uma Store Procedure buscando os dados em um tabela temporária e executar a instrução de forma genérica (INSERT com SELECT, por exemplo). Também pode-se usar um artifício do ASP.NET, Batch Update, para executar a instrução de forma genérica com alto desempenho.
* A depender da configuração do SQL Server, ao invés de ser o recurso interno (ou internal) pode ser o recurso default.
"There is insufficient system memory in resource pool 'internal' to run this query" *
ou
"Há memória de sistema insuficiente no pool de recursos internos para executar essa consulta" *
Isso ocorre quando há várias instruções SQL sendo executadas em seqüência. Como o pool não aguenta, os dados, em algumas vezes, podem travar... Mesmo que fisicamente eles estejam lá, não se pode mais ser utilizados até que o banco seja reiniciado. Para corrigir esse problema há duas formas: instalar o hotfix que a Microsoft disponibilizou ou reduzir quantidade de instruções a serem executadas por vez.
1) Instalar o HotFix
O arquivo está disponível em um pack cumulativo pós SP1 do SQL Server 2008. Para mais informações e download, clique aqui.
2) Reduzir a quantidade de instruções SQL
Fazendo um teste de vários UPDATE's seguidos, consegui obter tal erro. Gerei um arquivo .sql com quase 100mil updates e mandei o SQL Server executar, daí obtive o erro. Nunca tente isso! Se desejar executar vários UPDATE's ou INSERT's de vez fragmente a execução das instruções em blocos (nem tão grandes e nem tão pequenos) dando uma pausa entre as execuções. Pode-se utilizar uma Store Procedure buscando os dados em um tabela temporária e executar a instrução de forma genérica (INSERT com SELECT, por exemplo). Também pode-se usar um artifício do ASP.NET, Batch Update, para executar a instrução de forma genérica com alto desempenho.
* A depender da configuração do SQL Server, ao invés de ser o recurso interno (ou internal) pode ser o recurso default.
Gerando Gráficos em ASP.NET
Um componente que gosto de utilizar para gerar gráficos é o FusionCharts. Através dele é possível criar gráficos animados e interativos em Flash como gráficos em pizza, barra, colunas, funil, linha, área, bolha, etc. Além de trabalhar com ASP, ASP.NET, PHP, JSP, ColdFusion, Ruby on Rails, Python e HTML puro, pode-se utilizar em conjunto com bancos de dados como SQL Server, Oracle, MySQL, PostgreSQL, etc... O seu funcionamento consiste em apenas gerar o XML (em tempo de execução ou não) e indicar qual o gráfico. Vamos à prática...
Acesse o site da FusionCharts e baixe o pacote com os gráficos (na versão trial vem apenas os gráficos comuns - os mais complexos vem na versão paga). No arquivo baixado vem os SWF's dos gráficos, exemplos de XML's a serem gerados para cada gráficos, o JavaScript a ser incorporado na página e demais documentos (qualquer dúvida veja na pasta Code > CSNET que contêm um exemplo em ASP.NET e contêm todos os arquivos que irá precisar). Para nosso exemplo, vamos gerar um gráfico em pizza.
Crie um Web Site e adicione as pastas conforme a estrutura abaixo:
Adicione no App_Code as classes Util.cs e DbConn.cs. Na Bin adicione a referência à DLL da FusionCharts.dll, na Graficos adicione o SWF do gráfico que iremos gerar (no caso escolha o Pizza3D.swf) e na pasta Js adicione o FusionCharts.js. Todos esses arquivos são encontrados no ZIP que baixou no mesmo caminho dito anteriormente.
Adicione uma página ASPX agora e adicione no body ou no head o script:
<script language="Javascript" type="text/javascript" src="js/FusionCharts.js"></script>
Também adicione um Literal (Controle) no local onde deverá surgir o gráfico. Para fins didáticos coloque o ID do controle como GraphPizza. Agora tudo será no Code-Behind... Adicione os namespaces Utilities e InfoSoftGlobal usando a cláusula using. Em seguida criamos um método onde é gerado o XML e encapsulado sobre o SWF da seguinte forma:
public void CriarGraficoPizza3D()
{
string strXML = "<graph showNames='1' caption='Tipos de Clientes' decimalPrecision='0'>";
strXML += "<set name='Alvos' value='10' color='ED1C24'/>";
strXML += "<set name='Prospects' value='5' color='FFFF00'/>";
strXML += "<set name='Clientes' value='2' color='00E600'/>";
strXML += "</graph>";
GraphPizza.Text = FusionCharts.RenderChart("Graficos/Pizza3D.swf", "", strXML, "GraficoPizza3D", "400", "300", false, false);
}
No caso, gero todo o XML contendo os dados a serem apresentados e o passo por parâmetro ao método do FusionCharts para renderizá-lo e exibi-lo. Bem simples, não? Esse é o exemplo mais fácil... Há várias formas de apresentá-lo bem como suas opções fazem com que apresente mais variantes. O mais difícil (quer dizer trabalhoso) é gerar o XML...
Acesse o site da FusionCharts e baixe o pacote com os gráficos (na versão trial vem apenas os gráficos comuns - os mais complexos vem na versão paga). No arquivo baixado vem os SWF's dos gráficos, exemplos de XML's a serem gerados para cada gráficos, o JavaScript a ser incorporado na página e demais documentos (qualquer dúvida veja na pasta Code > CSNET que contêm um exemplo em ASP.NET e contêm todos os arquivos que irá precisar). Para nosso exemplo, vamos gerar um gráfico em pizza.
Crie um Web Site e adicione as pastas conforme a estrutura abaixo:
Adicione no App_Code as classes Util.cs e DbConn.cs. Na Bin adicione a referência à DLL da FusionCharts.dll, na Graficos adicione o SWF do gráfico que iremos gerar (no caso escolha o Pizza3D.swf) e na pasta Js adicione o FusionCharts.js. Todos esses arquivos são encontrados no ZIP que baixou no mesmo caminho dito anteriormente.
Adicione uma página ASPX agora e adicione no body ou no head o script:
<script language="Javascript" type="text/javascript" src="js/FusionCharts.js"></script>
Também adicione um Literal (Controle) no local onde deverá surgir o gráfico. Para fins didáticos coloque o ID do controle como GraphPizza. Agora tudo será no Code-Behind... Adicione os namespaces Utilities e InfoSoftGlobal usando a cláusula using. Em seguida criamos um método onde é gerado o XML e encapsulado sobre o SWF da seguinte forma:
public void CriarGraficoPizza3D()
{
string strXML = "<graph showNames='1' caption='Tipos de Clientes' decimalPrecision='0'>";
strXML += "<set name='Alvos' value='10' color='ED1C24'/>";
strXML += "<set name='Prospects' value='5' color='FFFF00'/>";
strXML += "<set name='Clientes' value='2' color='00E600'/>";
strXML += "</graph>";
GraphPizza.Text = FusionCharts.RenderChart("Graficos/Pizza3D.swf", "", strXML, "GraficoPizza3D", "400", "300", false, false);
}
No caso, gero todo o XML contendo os dados a serem apresentados e o passo por parâmetro ao método do FusionCharts para renderizá-lo e exibi-lo. Bem simples, não? Esse é o exemplo mais fácil... Há várias formas de apresentá-lo bem como suas opções fazem com que apresente mais variantes. O mais difícil (quer dizer trabalhoso) é gerar o XML...
Corrigindo dois erros em uma tacada só: O provedor “Microsoft.Jet.OLEDB.4.0” não está registrado na máquina local e O inicializador de tipo de 'CrystalDecisions.CrystalReports.Engine.ReportDocument' acionou uma exceção.
Problema: Porque o sistema operacional é 64bits.
Solução: Modo de compatibilidade em 32bits.
Bom se todo post fosse assim tão rápido para solucionar nossos problemas. Agora vamos alongar mais as respostas e enriquecer nosso conteúdo:
1) O provedor “Microsoft.Jet.OLEDB.4.0” não está registrado na máquina local
Se por ventura você recebeu esse erro ao executar uma query em um banco de dados usando OleDb mesmo que tenha o Microsoft Office instalado corretamente é porque provavelmente a versão do driver instalado é para 32bits. Para corrigir isso, sua aplicação deve rodar em 32bits (x86). Nesse post aqui é mostrado como compilar sua aplicação desktop em x86 exclusivamente solucionando o problema. Mas para quem usa aplicações desktop terá que mudar a configuração do pool de aplicação no IIS. Para isso vá no IIS, Pools de Aplicativos e selecione o Pool usado pelas suas aplicações. Clique em Configurações Avançadas e no item Habilitar Aplicativos 32bits configure para True.
2) O inicializador de tipo de 'CrystalDecisions.CrystalReports.Engine.ReportDocument' acionou uma exceção
Caso bem semelhante ao anterior ocorre se sua máquina é 64bits e instalar o Crystal Reports 32bits (x86). O modo de compatibilidade que o Windows coloca para aplicações instaladas não funciona no caso. Para resolver isso basta instalar a versão 64bits do Crystal Reports (x64). Mas se você realizou o passo acima e está habilitado o modo de compatibilidade de 32bits no IIS então terá que usar a versão 32bits do Crystal de qualquer jeito.
Solução: Modo de compatibilidade em 32bits.
Bom se todo post fosse assim tão rápido para solucionar nossos problemas. Agora vamos alongar mais as respostas e enriquecer nosso conteúdo:
1) O provedor “Microsoft.Jet.OLEDB.4.0” não está registrado na máquina local
Se por ventura você recebeu esse erro ao executar uma query em um banco de dados usando OleDb mesmo que tenha o Microsoft Office instalado corretamente é porque provavelmente a versão do driver instalado é para 32bits. Para corrigir isso, sua aplicação deve rodar em 32bits (x86). Nesse post aqui é mostrado como compilar sua aplicação desktop em x86 exclusivamente solucionando o problema. Mas para quem usa aplicações desktop terá que mudar a configuração do pool de aplicação no IIS. Para isso vá no IIS, Pools de Aplicativos e selecione o Pool usado pelas suas aplicações. Clique em Configurações Avançadas e no item Habilitar Aplicativos 32bits configure para True.
2) O inicializador de tipo de 'CrystalDecisions.CrystalReports.Engine.ReportDocument' acionou uma exceção
Caso bem semelhante ao anterior ocorre se sua máquina é 64bits e instalar o Crystal Reports 32bits (x86). O modo de compatibilidade que o Windows coloca para aplicações instaladas não funciona no caso. Para resolver isso basta instalar a versão 64bits do Crystal Reports (x64). Mas se você realizou o passo acima e está habilitado o modo de compatibilidade de 32bits no IIS então terá que usar a versão 32bits do Crystal de qualquer jeito.
Refresh automático ou execução de script em ciclos
Postado por
Thiago Marçal
on domingo, 18 de julho de 2010
/
Marcadores:
ajax,
html,
javascript
/
Comments: (1)
Durante o desenvolvimento de muitos sistemas web nos deparamos com as seguintes situações:
Situação 1: Atualizar página automacatimente
Para essa situação, que é a mais simples, basta inserir a seguinte tag no head da página especificando a quantidade de segundos que deve aguardar para dar o refresh:
Situação 2: Executar uma função JavaScript a cada x segundos
Se derem uma olhada no post anterior do chat, verão que uso uma função chamada setTimeout() que irá registrar qual função irá executar e qual o tempo de espera. Então, coloque o seguinte código JS:
window.onload = function() {
setTimeout("FuncaoJS()", 10000);
}
function FuncaoJS(){
// Instruções
setTimeout("FuncaoJS()", 10000);
}
De forma similar, pode-se usar também a função setInterval().
Situação 3: Executar um método ASP.NET a cada x segundos sem dar refresh
Já para o ASP.NET podemos usar o AJAX. Para isso utilizaremos um Timer e um UpdatePanel. Na página, adicione o ScriptManager e insira o Timer dentro do ContentTemplate do UpdatePanel. Atribua um método no evento OnTick do Timer ficando da seguinte forma:
<Ajax:ScriptManager ID="ScriptManagerAjax" runat="server">
</Ajax:ScriptManager>
<Ajax:UpdatePanel ID="Painel" runat="server">
<ContentTemplate>
<Ajax:Timer ID="Temporizador" runat="server" Interval="10000" OnTick="ExecutaScript_Tick">
</Ajax:Timer>
</ContentTemplate>
</Ajax:UpdatePanel>
Se você deixar o Timer fora do UpdatePanel ele irá realizar a execução do bloco de script, mas irá dar PostBack e, consequentemente, refresh na página. Por isso, e mais amigável, deve-se deixar dentro.
Agora basta criar o método no Code-Behind contendo o código a ser executado:
protected void ExecutaScript_Tick(object sender, EventArgs e)
{
}
Tranquilo, né?
- Página dar refresh automaticamente a cada x segundos;
- Executar um bloco de script (JavaScript) a cada x segundos;
- Executar um bloco de código (ASP.NET) a cada x segundos sem refresh na página.
Situação 1: Atualizar página automacatimente
Para essa situação, que é a mais simples, basta inserir a seguinte tag no head da página especificando a quantidade de segundos que deve aguardar para dar o refresh:
<META HTTP-EQUIV="Refresh"
CONTENT="10;URL=http://thiagomarcal.blogspot.com">
Situação 2: Executar uma função JavaScript a cada x segundos
Se derem uma olhada no post anterior do chat, verão que uso uma função chamada setTimeout() que irá registrar qual função irá executar e qual o tempo de espera. Então, coloque o seguinte código JS:
window.onload = function() {
setTimeout("FuncaoJS()", 10000);
}
function FuncaoJS(){
// Instruções
setTimeout("FuncaoJS()", 10000);
}
De forma similar, pode-se usar também a função setInterval().
Situação 3: Executar um método ASP.NET a cada x segundos sem dar refresh
Já para o ASP.NET podemos usar o AJAX. Para isso utilizaremos um Timer e um UpdatePanel. Na página, adicione o ScriptManager e insira o Timer dentro do ContentTemplate do UpdatePanel. Atribua um método no evento OnTick do Timer ficando da seguinte forma:
<Ajax:ScriptManager ID="ScriptManagerAjax" runat="server">
</Ajax:ScriptManager>
<Ajax:UpdatePanel ID="Painel" runat="server">
<ContentTemplate>
<Ajax:Timer ID="Temporizador" runat="server" Interval="10000" OnTick="ExecutaScript_Tick">
</Ajax:Timer>
</ContentTemplate>
</Ajax:UpdatePanel>
Se você deixar o Timer fora do UpdatePanel ele irá realizar a execução do bloco de script, mas irá dar PostBack e, consequentemente, refresh na página. Por isso, e mais amigável, deve-se deixar dentro.
Agora basta criar o método no Code-Behind contendo o código a ser executado:
protected void ExecutaScript_Tick(object sender, EventArgs e)
{
}
Tranquilo, né?
Criando um Chat em ASP.NET em 1 minuto
Para quem quer ter um chat em seu web site, esse componente é uma mão na roda. Muito fácil de ser utilizado e configurado, apesar de seus bugs (irei solucioná-los no fim do post). Em poucos segundos você tem um chat funcional! A Web Furbish desenvolveu esse componente e pode ser encontrado tanto aqui quanto aqui e em vários mirros pela net. Vamos ao desenvolvimento...
Extraia os arquivos em um local onde poderá buscá-los. Agora crie um novo Web Site. Se for sua primeira vez usando o componente, primeiramente, deve-se adicionar o novo controle ao ToolBox do Visual Studio. Para isso, clique com o botão direito em algum local onde é exibido os itens e escolha a opção Choose Items:
Quando surgir a caixa de seleção de componentes, na aba .NET Framework Components, clique no botão Browse... para selecionar a DLL JaxterChat.dll na pasta onde extraiu os arquivos a princípio. Clique em OK para carregá-la. Verá que ela foi adicionada ao ToolBox. Esse passo foi o mais difícil! Em seguida copie a pasta JaxterChat (que havia junto à DLL) e incorpore-o a seu projeto. Nessa pasta contêm arquivos de imagem, som, etc. Agora é simples: arraste-o para a página para que ele seja adicionado. Pronto! Você já tem seu chat...
O resto é apenas configuração: tema, tempo de atualização, usar som, nome dos labels, etc. Veja como ficou o meu!
Tranquilo e prático, não? Antes dos bugs, vamos a alguns questionamentos?
1) Como faço para ter várias salas?
Você não precisar criar várias páginas para a cada sala. Basta que, no Page_Load, atribua o nome da sala ao controle. Exemplo: Chat.RoomName = "Blog"; O controle irá se encarregar de fazer a separação dos usuários de acordo com o nome da sala.
2) Como gravar o log das conversas?
Crie um método para o OnMessagePosted do chat. Você pode gravar em banco ou em arquivo. Ficaria mais ou menos assim:
protected void Grava_Log(object sender, WebFurbish.JaxterMessageEventArgs e)
{
string sala = e.RoomName;
string usuario = e.UserName;
string mensagemExibida = e.Message;
string mensagemHtml = e.MessageHTML;
string hora = DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss");
// Grava o log em banco ou em arquivo
}
3) Como enviar mensagens às salas (avisos de administração, etc) igual a um Broadcast?
Esse é um pouco mais complicado e demorado, então irei explicar em linhas gerais como seria:
O parâmetro false indica que essa mensagem não será processada em log (ou seja, não parassá pelo método do OnMessagePosted).
E n formas que há de customizar o chat para trabalhar da forma como desejar. Pois bem, agora vamos aos bugs encontrados. Quando levantei esses bugs enviei um e-mail para eles mas não obtive resposta até o momento (também nem tentei mais... :P).
Bug 1: A cada mensagem entrada, a barra de rolagem ao invés de acompanhar as mensagens, ela fica sempre apontada para o topo. Ou seja, ela não desce...
Notamos isso quando começa a encher de mensagens. A barra ao invés de rolar automaticamente para baixo, fica estagnada no topo. Analisando o JavaScript que ele gera, verifiquei que há um problema na função WF_goToBottomScroll. Daí, como não posso apagar ela, criei uma outra com o mesmo nome. Como há sobrecarga ela será executada também. É armengue, mas é uma solução. Como funciona essa solução? A cada 0 segundos verifico se o foco está no campo de texto digitado: se estiver, a barra da div rola automaticamente para baixo. Para que isso funcione, baixe esse script aqui para fazer uma varredura de controles HTML. E adicione o seguinte bloco de código JS na página que contêm o chat:
window.onload = function() {
setFocusTracking();
sizeMsgOut = document.getElementById('WF_msgOut').scrollHeight;
setTimeout("WF_goToBottomScroll('WF_msgOut');", 0);
}
function WF_goToBottomScroll(elemento) {
var msgOut = document.getElementById(elemento);
if (document.hasFocus) {
if (document.hasFocus.id == 'WF_textInput')
msgOut.scrollTop = msgOut.scrollHeight;
}
setTimeout("WF_goToBottomScroll('" + elemento + "');", 0);
}
Bug 2: O som não funciona!
Quando vi que iria ter som, pensei: "Bala!". Mas daí ele exige Java para rodar. Pensei novamente: "Tranquilo! Hoje na net, em sites de banco, tem que ter Java, logo pro chat vai ser pré-requisito ter também.". Instalei a versão mais recente e não funcionou! Porque, eu não sei. Como o componente é fechado, a única coisa que deu para ver é que ele chama uma classe Java SoundApplet.class já compilada. Enfim, providenciei outra solução: coloquei a propriedade EnableSound como false e adicionei algumas linhas ao script WF_goToBottomScroll para tocar um som a cada vez que é dado uma entrada de mensagem. Esse som é puro JavaScript! Primeiro, adicione uma tag de som em background em qualquer local da página, assim:
Depois crie uma variável global var sizeMsgOut = 0; antes do window.onload . Ou seja, estou criando uma variável global que irá armazenar o tamanho de minha div a cada momento e quando entrar na página pela primeira vez terá valor 0. Agora, adicione as linhas abaixo na função WF_goToBottomScroll antes do setTimeout:
if (document.getElementById('WF_msgOut').scrollHeight != sizeMsgOut) {
document.all.sound.src = "JaxterChat/Sounds/alert.au";
sizeMsgOut = document.getElementById('WF_msgOut').scrollHeight;
}
A cada iteração da função, verifico se o tamanho da div que contêm as mensagens é diferente do valor armazenado na variável. Se for é porque entrou nova mensagem logo deve tocar o som.
Esses foram dois bugs que encontrei quando estava usando-o. Pode ser que haja outros que não encontrei. Se não tiver é bom, pois é um chat bem legalzinho e fácil e manipular. Até mais!
Extraia os arquivos em um local onde poderá buscá-los. Agora crie um novo Web Site. Se for sua primeira vez usando o componente, primeiramente, deve-se adicionar o novo controle ao ToolBox do Visual Studio. Para isso, clique com o botão direito em algum local onde é exibido os itens e escolha a opção Choose Items:
Quando surgir a caixa de seleção de componentes, na aba .NET Framework Components, clique no botão Browse... para selecionar a DLL JaxterChat.dll na pasta onde extraiu os arquivos a princípio. Clique em OK para carregá-la. Verá que ela foi adicionada ao ToolBox. Esse passo foi o mais difícil! Em seguida copie a pasta JaxterChat (que havia junto à DLL) e incorpore-o a seu projeto. Nessa pasta contêm arquivos de imagem, som, etc. Agora é simples: arraste-o para a página para que ele seja adicionado. Pronto! Você já tem seu chat...
O resto é apenas configuração: tema, tempo de atualização, usar som, nome dos labels, etc. Veja como ficou o meu!
Tranquilo e prático, não? Antes dos bugs, vamos a alguns questionamentos?
1) Como faço para ter várias salas?
Você não precisar criar várias páginas para a cada sala. Basta que, no Page_Load, atribua o nome da sala ao controle. Exemplo: Chat.RoomName = "Blog"; O controle irá se encarregar de fazer a separação dos usuários de acordo com o nome da sala.
2) Como gravar o log das conversas?
Crie um método para o OnMessagePosted do chat. Você pode gravar em banco ou em arquivo. Ficaria mais ou menos assim:
protected void Grava_Log(object sender, WebFurbish.JaxterMessageEventArgs e)
{
string sala = e.RoomName;
string usuario = e.UserName;
string mensagemExibida = e.Message;
string mensagemHtml = e.MessageHTML;
string hora = DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss");
// Grava o log em banco ou em arquivo
}
3) Como enviar mensagens às salas (avisos de administração, etc) igual a um Broadcast?
Esse é um pouco mais complicado e demorado, então irei explicar em linhas gerais como seria:
- Pegaria todas as sala usando o método GetRoomList();
- E para cada sala faz-se o envio através do método SendCustomMessage().
O parâmetro false indica que essa mensagem não será processada em log (ou seja, não parassá pelo método do OnMessagePosted).
E n formas que há de customizar o chat para trabalhar da forma como desejar. Pois bem, agora vamos aos bugs encontrados. Quando levantei esses bugs enviei um e-mail para eles mas não obtive resposta até o momento (também nem tentei mais... :P).
Bug 1: A cada mensagem entrada, a barra de rolagem ao invés de acompanhar as mensagens, ela fica sempre apontada para o topo. Ou seja, ela não desce...
Notamos isso quando começa a encher de mensagens. A barra ao invés de rolar automaticamente para baixo, fica estagnada no topo. Analisando o JavaScript que ele gera, verifiquei que há um problema na função WF_goToBottomScroll. Daí, como não posso apagar ela, criei uma outra com o mesmo nome. Como há sobrecarga ela será executada também. É armengue, mas é uma solução. Como funciona essa solução? A cada 0 segundos verifico se o foco está no campo de texto digitado: se estiver, a barra da div rola automaticamente para baixo. Para que isso funcione, baixe esse script aqui para fazer uma varredura de controles HTML. E adicione o seguinte bloco de código JS na página que contêm o chat:
window.onload = function() {
setFocusTracking();
sizeMsgOut = document.getElementById('WF_msgOut').scrollHeight;
setTimeout("WF_goToBottomScroll('WF_msgOut');", 0);
}
function WF_goToBottomScroll(elemento) {
var msgOut = document.getElementById(elemento);
if (document.hasFocus) {
if (document.hasFocus.id == 'WF_textInput')
msgOut.scrollTop = msgOut.scrollHeight;
}
setTimeout("WF_goToBottomScroll('" + elemento + "');", 0);
}
Bug 2: O som não funciona!
Quando vi que iria ter som, pensei: "Bala!". Mas daí ele exige Java para rodar. Pensei novamente: "Tranquilo! Hoje na net, em sites de banco, tem que ter Java, logo pro chat vai ser pré-requisito ter também.". Instalei a versão mais recente e não funcionou! Porque, eu não sei. Como o componente é fechado, a única coisa que deu para ver é que ele chama uma classe Java SoundApplet.class já compilada. Enfim, providenciei outra solução: coloquei a propriedade EnableSound como false e adicionei algumas linhas ao script WF_goToBottomScroll para tocar um som a cada vez que é dado uma entrada de mensagem. Esse som é puro JavaScript! Primeiro, adicione uma tag de som em background em qualquer local da página, assim:
<BGSOUND id="sound" src="">
Depois crie uma variável global var sizeMsgOut = 0; antes do window.onload . Ou seja, estou criando uma variável global que irá armazenar o tamanho de minha div a cada momento e quando entrar na página pela primeira vez terá valor 0. Agora, adicione as linhas abaixo na função WF_goToBottomScroll antes do setTimeout:
if (document.getElementById('WF_msgOut').scrollHeight != sizeMsgOut) {
document.all.sound.src = "JaxterChat/Sounds/alert.au";
sizeMsgOut = document.getElementById('WF_msgOut').scrollHeight;
}
A cada iteração da função, verifico se o tamanho da div que contêm as mensagens é diferente do valor armazenado na variável. Se for é porque entrou nova mensagem logo deve tocar o som.
Esses foram dois bugs que encontrei quando estava usando-o. Pode ser que haja outros que não encontrei. Se não tiver é bom, pois é um chat bem legalzinho e fácil e manipular. Até mais!
Gerando o Código de Verificação (CODVER) para o Komerci em ASP.NET ou em Qualquer Linguagem
Quem está começando a fazer a integração de sua loja virtual com o Komerci e está lendo o manual da versão Integrada, se deparou com a parte da geração do código de verificação. Eles disponibilizam uma classe Java denominada CodVer.class. Daí você pensa: "Para eles disponibilizarem uma classe específica em Java deve ser porque é algo muito específico ou cabuloso!". Mas não é... Não sei porque no próprio manual eles não colocam um pseudo-algoritmo ou diagramas que possam facilitar para a elaboração nas demais linguagens. No mesmo manual eles dizem que disponibilizam um ActiveX para quem usa ASP Clássico. É de dar risada! Bem, o código é bem simples. Já converti do Java para C# e, para quem está familiarizado com C/Java, vai entender o algoritmo rapidinho e elaborar o seu também:
public string GeraCodigoVerificao(string _numfil, string _valor)
{
// Início da codificação
string codigo = string.Empty;
// Número da filiação
int numfil = 0;
numfil = int.Parse(_numfil);
// Total
int total = 0;
string parteInteira = _valor.Substring(0, _valor.IndexOf('.'));
total = int.Parse(parteInteira);
// Codificação a hora
int segundosAgora = DateTime.Now.Second;
int segundosAgoraCodificados = 0;
switch (segundosAgora)
{
case 0:
segundosAgoraCodificados = 11;
break;
case 1:
segundosAgoraCodificados = 17;
break;
case 2:
segundosAgoraCodificados = 21;
break;
case 3:
segundosAgoraCodificados = 31;
break;
case 4:
segundosAgoraCodificados = 56;
break;
case 5:
segundosAgoraCodificados = 34;
break;
case 6:
segundosAgoraCodificados = 42;
break;
case 7:
segundosAgoraCodificados = 3;
break;
case 8:
segundosAgoraCodificados = 18;
break;
case 9:
segundosAgoraCodificados = 13;
break;
case 10:
segundosAgoraCodificados = 12;
break;
case 11:
segundosAgoraCodificados = 18;
break;
case 12:
segundosAgoraCodificados = 22;
break;
case 13:
segundosAgoraCodificados = 32;
break;
case 14:
segundosAgoraCodificados = 57;
break;
case 15:
segundosAgoraCodificados = 35;
break;
case 16:
segundosAgoraCodificados = 43;
break;
case 17:
segundosAgoraCodificados = 4;
break;
case 18:
segundosAgoraCodificados = 19;
break;
case 19:
segundosAgoraCodificados = 14;
break;
case 20:
segundosAgoraCodificados = 9;
break;
case 21:
segundosAgoraCodificados = 20;
break;
case 22:
segundosAgoraCodificados = 23;
break;
case 23:
segundosAgoraCodificados = 33;
break;
case 24:
segundosAgoraCodificados = 58;
break;
case 25:
segundosAgoraCodificados = 36;
break;
case 26:
segundosAgoraCodificados = 44;
break;
case 27:
segundosAgoraCodificados = 5;
break;
case 28:
segundosAgoraCodificados = 24;
break;
case 29:
segundosAgoraCodificados = 15;
break;
case 30:
segundosAgoraCodificados = 62;
break;
case 31:
segundosAgoraCodificados = 25;
break;
case 32:
segundosAgoraCodificados = 34;
break;
case 33:
segundosAgoraCodificados = 59;
break;
case 34:
segundosAgoraCodificados = 37;
break;
case 35:
segundosAgoraCodificados = 45;
break;
case 36:
segundosAgoraCodificados = 6;
break;
case 37:
segundosAgoraCodificados = 25;
break;
case 38:
segundosAgoraCodificados = 16;
break;
case 39:
segundosAgoraCodificados = 27;
break;
case 40:
segundosAgoraCodificados = 63;
break;
case 41:
segundosAgoraCodificados = 26;
break;
case 42:
segundosAgoraCodificados = 35;
break;
case 43:
segundosAgoraCodificados = 60;
break;
case 44:
segundosAgoraCodificados = 38;
break;
case 45:
segundosAgoraCodificados = 46;
break;
case 46:
segundosAgoraCodificados = 7;
break;
case 47:
segundosAgoraCodificados = 26;
break;
case 48:
segundosAgoraCodificados = 17;
break;
case 49:
segundosAgoraCodificados = 28;
break;
case 50:
segundosAgoraCodificados = 14;
break;
case 51:
segundosAgoraCodificados = 36;
break;
case 52:
segundosAgoraCodificados = 2;
break;
case 53:
segundosAgoraCodificados = 39;
break;
case 54:
segundosAgoraCodificados = 47;
break;
case 55:
segundosAgoraCodificados = 8;
break;
case 56:
segundosAgoraCodificados = 29;
break;
case 57:
segundosAgoraCodificados = 22;
break;
case 58:
segundosAgoraCodificados = 55;
break;
case 59:
segundosAgoraCodificados = 33;
break;
}
// Cálculos e atribuições
segundosAgora = segundosAgoraCodificados;
string pad = string.Empty;
if (segundosAgora < 10)
pad = "0";
else
pad = "";
string ipremoto = Request.ServerVariables["REMOTE_ADDR"];
int tamIP = ipremoto.Length;
int i_5_ = total + segundosAgora;
int i_6_ = segundosAgora + tamIP;
int i_7_ = segundosAgora * numfil;
int i_8_ = i_7_.ToString().Length;
// Monta o código
codigo = i_7_.ToString() + i_5_.ToString() + i_6_.ToString() + "-" + i_8_.ToString() + pad + segundosAgora.ToString();
// Retorna
return codigo;
}
public string GeraCodigoVerificao(string _numfil, string _valor)
{
// Início da codificação
string codigo = string.Empty;
// Número da filiação
int numfil = 0;
numfil = int.Parse(_numfil);
// Total
int total = 0;
string parteInteira = _valor.Substring(0, _valor.IndexOf('.'));
total = int.Parse(parteInteira);
// Codificação a hora
int segundosAgora = DateTime.Now.Second;
int segundosAgoraCodificados = 0;
switch (segundosAgora)
{
case 0:
segundosAgoraCodificados = 11;
break;
case 1:
segundosAgoraCodificados = 17;
break;
case 2:
segundosAgoraCodificados = 21;
break;
case 3:
segundosAgoraCodificados = 31;
break;
case 4:
segundosAgoraCodificados = 56;
break;
case 5:
segundosAgoraCodificados = 34;
break;
case 6:
segundosAgoraCodificados = 42;
break;
case 7:
segundosAgoraCodificados = 3;
break;
case 8:
segundosAgoraCodificados = 18;
break;
case 9:
segundosAgoraCodificados = 13;
break;
case 10:
segundosAgoraCodificados = 12;
break;
case 11:
segundosAgoraCodificados = 18;
break;
case 12:
segundosAgoraCodificados = 22;
break;
case 13:
segundosAgoraCodificados = 32;
break;
case 14:
segundosAgoraCodificados = 57;
break;
case 15:
segundosAgoraCodificados = 35;
break;
case 16:
segundosAgoraCodificados = 43;
break;
case 17:
segundosAgoraCodificados = 4;
break;
case 18:
segundosAgoraCodificados = 19;
break;
case 19:
segundosAgoraCodificados = 14;
break;
case 20:
segundosAgoraCodificados = 9;
break;
case 21:
segundosAgoraCodificados = 20;
break;
case 22:
segundosAgoraCodificados = 23;
break;
case 23:
segundosAgoraCodificados = 33;
break;
case 24:
segundosAgoraCodificados = 58;
break;
case 25:
segundosAgoraCodificados = 36;
break;
case 26:
segundosAgoraCodificados = 44;
break;
case 27:
segundosAgoraCodificados = 5;
break;
case 28:
segundosAgoraCodificados = 24;
break;
case 29:
segundosAgoraCodificados = 15;
break;
case 30:
segundosAgoraCodificados = 62;
break;
case 31:
segundosAgoraCodificados = 25;
break;
case 32:
segundosAgoraCodificados = 34;
break;
case 33:
segundosAgoraCodificados = 59;
break;
case 34:
segundosAgoraCodificados = 37;
break;
case 35:
segundosAgoraCodificados = 45;
break;
case 36:
segundosAgoraCodificados = 6;
break;
case 37:
segundosAgoraCodificados = 25;
break;
case 38:
segundosAgoraCodificados = 16;
break;
case 39:
segundosAgoraCodificados = 27;
break;
case 40:
segundosAgoraCodificados = 63;
break;
case 41:
segundosAgoraCodificados = 26;
break;
case 42:
segundosAgoraCodificados = 35;
break;
case 43:
segundosAgoraCodificados = 60;
break;
case 44:
segundosAgoraCodificados = 38;
break;
case 45:
segundosAgoraCodificados = 46;
break;
case 46:
segundosAgoraCodificados = 7;
break;
case 47:
segundosAgoraCodificados = 26;
break;
case 48:
segundosAgoraCodificados = 17;
break;
case 49:
segundosAgoraCodificados = 28;
break;
case 50:
segundosAgoraCodificados = 14;
break;
case 51:
segundosAgoraCodificados = 36;
break;
case 52:
segundosAgoraCodificados = 2;
break;
case 53:
segundosAgoraCodificados = 39;
break;
case 54:
segundosAgoraCodificados = 47;
break;
case 55:
segundosAgoraCodificados = 8;
break;
case 56:
segundosAgoraCodificados = 29;
break;
case 57:
segundosAgoraCodificados = 22;
break;
case 58:
segundosAgoraCodificados = 55;
break;
case 59:
segundosAgoraCodificados = 33;
break;
}
// Cálculos e atribuições
segundosAgora = segundosAgoraCodificados;
string pad = string.Empty;
if (segundosAgora < 10)
pad = "0";
else
pad = "";
string ipremoto = Request.ServerVariables["REMOTE_ADDR"];
int tamIP = ipremoto.Length;
int i_5_ = total + segundosAgora;
int i_6_ = segundosAgora + tamIP;
int i_7_ = segundosAgora * numfil;
int i_8_ = i_7_.ToString().Length;
// Monta o código
codigo = i_7_.ToString() + i_5_.ToString() + i_6_.ToString() + "-" + i_8_.ToString() + pad + segundosAgora.ToString();
// Retorna
return codigo;
}





