Deletado em 13 de setembro de 2010

Feliz dia do Programador

Pena que no Brasil ainda não temos essa cultura =)

Mas hoje é dia do programador, então, parabéns à todos que tem essa profissão!!! Ou tentam ter hahahahahaha.

Abraços!

Deletado em 10 de agosto de 2010

SELECT com NULL no MS SQL

Uma postagem rápida para falar sobre SQL e aproveitar para dizer que tive 2 artigos publicados na SQL Magazine deste mês de Agosto (Edição 78). \o/ hehehehe!!!!

Então... Acabei de me deparar com um problema bobo hoje. Estava criando um procedure que tinha um status do tipo Bit.

Para chamar a procedure passava 0 ou 1... Maravilha!

Entretanto, no sistema no qual a procedure ia ser chamada, poderia listar os ativos, inativos ou os ativos (E) inativos.

Poxa que fácil, basta apenas passar no parâmetro do status o valor NULL.

Vamos ao exemplo:

CREATE PROCEDURE [dbo].[ListarNulo] 
 @Status BIT
AS
BEGIN

 SELECT 
     [ParceiroCodigo]
    ,[CPF]
    ,[NumMatricula]
   FROM [ListaBranca] 
 WHERE
  ([Status] = @Status OR @Status = NULL)

END

Poxa, que nada de diferente, pronto acabou! Éééé... não, infelizmente quando rodei a procedure passando NULL no parâmetro... Não me trouxe nada! Mas pq???

Bom, foram 10 minutos revisando a procedure (não era essa acima, era uma maiorzinha) e mas 10 minutos para descobrir e bater a mão na testa dizendo "nossa como eu sou burro".

A frase do que eu precisa me dizia a resposta. "Preciso verificar se o parâmetro (É) nulo." "É" nulo e não "Igual" a Nulo. Vamos alterar a procedure.

ALTER PROCEDURE [dbo].[ListarNulo] 
 @Status BIT
AS
BEGIN

 SELECT 
     [ParceiroCodigo]
    ,[CPF]
    ,[NumMatricula]
   FROM [ListaBranca] 
 WHERE
  ([Status] = @Status OR @Status IS NULL)

END

Podemos ver que tirei o igual e coloquei a cláusula IS, apenas para verificar se é nulo. Resolvido! IS um lixo mesmo... Abraços!

Deletado em 26 de julho de 2010

Diferenças entre ASP.Net Web Services e WCF (Windows Comunication Fundation)

Encontro poucas informações sobre WCF atualmente na Internet. Na verdade pouco usei esta tecnologia, mas quando começei a pesquisar sobre a maior dúvida era: O que WCF tem de diferente dos Web Services.

Para um conteúdo completo, recomendo o blog do MVP Israel Aece. Ele fez alguns vídeos e explica muitas coisas do WCF, falando também as diferenças entre as tecnologias.

A partir do blog dele, tentei fazer uma tabela básica com o que existe em Web Services e o que existe no WCF. O Resultado é o lixo abaixo:

Ação Web Services WCF
Estrutura de
Projeto
Arquivos .asmx, trabalha com métodos de serviço. Arquivos .srv, trabalha com contratos de serviços.
Contratos Obrigatório o uso atributo [WebMethod] em cada método que estará disponível para o acesso. Interfaces determinam os contratos, decoradas com [ServiceContract]. Pode ter tipos complexos vinculados aos serviços.
Serialização/
Deserialização
Serializa todos os membros públicos com XmlSerializer. Utiliza o DataContractSerializer, parecido com XmlSerializer porém persiste membros private e protected e gera um XML mais simplificado, melhorando a interoperabilidade entre as plataformas.
Protocolo/
Hosting
Pode somente ser hospedado no IIS, utilizando o protocolo HTTP/HTTPS. Arquitetura muito mais flexível e é independente do protocolo, ou seja, ele pode rodar em HTTP, HTTPS, TCP, MSMQ, etc. Pode usar o IIS como host ou ser um serviço instalado no Windows.
Extensibilidade Interceptar as requisições através de SOAP Extensions. Inúmeros pontos de extensibilidade tanto do lado do serviço quanto do cliente.
Segurança Segurança baseada no transporte, ou seja, ele somente será seguro se você expor o serviço através de HTTPS. Pode utilizar SoapHeader com usuário e senha. Funciona bem, mas é vulnerável. É seguro por padrão. Para utilizar a autenticação baseada em UserName/Password que o WCF fornece sob o protocolo HTTP, será necessário utilizar um certificado.
Configuração Utiliza a Web.config de forma declarativa Seção de configurações são extremamente ricas. Segurança, transações, know types, behaviors, bindings, endpoints, contratos, etc. É um pouco complexo. Grande parte do que temos no WCF não existe nativamente no ASMX.
Interoperabilidade Interoperabilidade O ASMX não possui nativamente suporte a especificações que foram definidas por grandes "players" do mercado. Precisa da instalação de um Add-on para o Visual Studio .NET. Padrões já foram implementados nativamente e são configuráveis. Consegue facilmente conversar com serviços construídos em ASMX em ambos os lados.
Cliente Pode ser integrado com muitas aplicações. Muito mais flexível que o ASMX.
Desempenho http://msdn.microsoft.com/en-us/library/bb310550.aspx
Resultado
Final
Gera WSDL Gera WSDL
Conclusão Muitas funcionalidades ainda são de forma idêntica entre o WS e o WCF.

Quanto a questões de configuração, segurança, desempenho e Interoperabilidade o WCF ganha por ter todos os padrões de XML adicionados nativamente, englobar todas as tecnologias de computação distribuída da Microsoft e ser mais flexível a alterações e extensibilidade.

Os Web Services são pouco mais fáceis de se trabalhar quanto a questão de criação de projeto e análise de erros. Entretanto a questão de desenvolvimento o WCF é bem mais avançado. Por fim, os dois geram WSDL para o cliente consumir os dados.

Se colocarmos em uma balança as duas tecnologias. Realmente pouca coisa parece ter mudado.

Entretanto, pensando no seguinte fato: Se hoje minha empresa vai começar a criar algo orientado a serviços, deveriamos usar o WCF, pois é uma nova tecnologia que vai substituir o Web Services.

Agora, fazer a migração das tecnologias, talvez isso ainda (atualmente) não vale tanto a pena. Pelo mesmo motivo de "parecer" o mesmo da mesma coisa.

Deletado em 20 de julho de 2010

Como funcionam as Arrays (Matrizes) Multidimensionais no C#?

Bem simples essa resposta. Funciona como esta na imagem acima =).

Ok, não é tão simples. Mas ai está o ponto deste lixo de post. As matrizes, ou como chamamos no C# arrays, multidimensionais são, como muitos professores de faculdade dizem, uma caixa de Biz, ou melhor, linha e coluna igual na matemática.

E eles estão certos. É isso mesmo. Mas não é como o C# trata isso internamente.

Arrays são Reference Types, traduzindo, variáveis por referência (para quem não sabe, existem 2 tipos, os tipos por referência e os por valor, os Value Types). Os Reference Types guardão, ao invés do valor da variável, o endereço de memória no qual este valor está disponível.

Entendendo isso, vamos a Array. Imaginando a seguinte entrada do programa:

int[,] x = new int[2, 3];
x[1, 2] = 10;

Na primeira linha, criamos uma matriz “x” de inteiros com 2 linhas e 3 colunas. Na realidade, inserimos na memória stack (Pilha) um endereço, podemos ver essa ação na imagem acima (e todas as outras ações também =P). Podemos ver que “x” guarda o endereço de memória “adew:12ws”.

A partir dessa posição de memória podemos entender como o C# se comporta.

Como temos uma array de 2 por 3, vamos ter primeiro neste endereço (“adew:12ws”) outros dois endereços conforme solicitamos na “linha” [2, 3], e esses dois endereços terão as quantidades (três neste caso) de VALORES que solicitamos na "coluna" [2, 3].

Eu disse valores em maiúscula pois realmente na última instrução da array não teremos mais apontamento para memória e sim o valor real guardado. Esse valor é iniciado zero para todas as 6 possibilidades.

E como funciona a troca de valor, como a segunda linha de instrução diz x[1, 2] = 10? Na imagem podemos ver passo a passo como funciona.

A variável "x", guarda o endereço “adew:12ws” que em 0 guarda o endereço “apop:1234” e em 1 guarda o endereço “eeee:uuuu” (lembrando que as posições da array sempre começam com 0 e terminam em valor - 1). Vamos trocar o valor na linha 1 (“apop:1234” em “adew:12ws”) da coluna 2 (valor 0 em “apop:1234”) para 10 (risca o zero e coloca o 10). Pronto assim o C# trata as arrays multidimensionais.

E se tivéssemos mais uma dimensão?

int[,,] x = new int[2, 3, 2];

A mesma idéia iria se aplicar, onde "x" apontaria para um endereço de memória (como na pilha vista) com 2 endereços de memória [2, 3, 2]. Esses dois endereços apontariam para mais três endereços de memória [2, 3, 2] e cada um desses endereços de memória teriam 2 valores [2, 3, 2]. Como muita coisa na informática é feita uma árvore de dados.

Esse post foi um pedaço da aula de orientação a objetos avançada que fiz junto com minha empresa com o professor Agnaldo no centro de treinamento 50 minutos. Achei realmente muito interessante.

Abraços.

Deletado em 5 de julho de 2010

Charges

Ok, isso acontece em todas empresas =)

Esse eu editei pois o ratinho estudava C++, agora é um ratinho que estuda C#!

Lixo para descontrair...

Deletado em 24 de junho de 2010

Procurando elementos em uma lista genérica (Exists(), Find(), FindAll(), RemoveAll())

Temos listas genéricas no Framework do .Net desde a versão 2.0. A primeira vez que eu vi já adorei pelo fato de aumentar o desempenho devido a não necessidade de conversão de tipos. Outro ponto é a segurança, pelo mesmo motivo da tipagem, antigamente nos ArrayLists poderíamos sem querer colocar uma string dentro de uma lista de inteiros, e só descobrir isso em execução. Por fim, também temos um código enxuto.

Então, lista genérica não é novidade, encontramos vários exemplos na Internet de como criá-las. Também encontramos exemplos de como fazer filtros ou encontrar objetos dentro das listas, mas são um pouco mais complexos de se achar e quando encontrados não são muito explicativos. Por isso então, este post vai pro lixo.

Vamos criar uma Lista de Pessoas, básico para estudar esse tipo de assunto (Vou usar um ConsoleApplication):

public class Pessoa
{
    private string Nome { get; set; }
    private Int16 Idade { get; set; }
    private char Sexo { get; set; }

    public Pessoa(string nome, Int16 idade, char sexo)
    {
        Nome = nome;
        Idade = idade;
        Sexo = sexo;
    }
    
    public Pessoa()
    {
         Nome = string.Empty;
         Idade = 0;
         Sexo = char.MinValue;
    }
}
class Program
{
    static void Main(string[] args)
    {
        List<Pessoa> lstPessoas = new List<Pessoa>();

        lstPessoas.Add(new Pessoa("Adriano Galesso", 23, 'M'));
        lstPessoas.Add(new Pessoa("Manuela Bognar", 21, 'F'));
        lstPessoas.Add(new Pessoa("Pedro Alberto Braga", 44, 'M'));
        lstPessoas.Add(new Pessoa("Rosalinda da Silva", 75, 'F'));

        Existe(lstPessoas);
        Procura(lstPessoas);
        Remove(lstPessoas);

        Console.ReadLine();
    }
}

Temos uma lista com 4 objetos Pessoa. Agora vamos começar a “brincar” com nossa lista.

Primeiramente vamos criar um método que verifica se existem alguns nomes em nossa Lista. Para isso vamos utilizar a função Exists da lista genérica.

private static void Existe(List<Pessoa> lstPessoas)
{
    string[] nomePesquisa = new string[] { "Adriano", "Margarida", "Pedro", "Marcos", "Graciele" };

    for (int i = 0; i < nomePesquisa.Length; i++)
    {
        Console.WriteLine(lstPessoas.Exists(
            delegate(Pessoa pessoa)
            {
                return pessoa.Nome.IndexOf(nomePesquisa[i]) >= 0;
            }) ? 
            nomePesquisa[i] + " Existe na Lista" : 
            nomePesquisa[i] + " Não Existe na Lista");
    }

    Console.WriteLine("\n");
}

Neste método temos uma array de strings com nomes para pesquisar na lista. Para cada string vamos mostrar se existe ou não o nome da lista (mesmo que parte do nome).

Passamos uma lista de pessoas para o método fazer a verificação. Para a verificação foi utilizada a função Exists. Esta função espera um System.Predicate tipado, ou seja, um delegate que contém a regra para a busca dentro da lista. Sendo mais especifico, devemos delegar uma função para fazer qualquer condição que gostaríamos.

Neste caso o delegate fará a verificação de cada objeto pessoa em nossa lista, vendo se parte do Nome contém as strings da nossa array de pesquisa. Se tiver escrevemos uma coisa e se não tiver escrevemos outra.

Basicamente o mais importante de toda a busca é o delegate. Em uma função delegate, deve-se retornar sempre um boleano. Neste caso usamos o delegate junto com o próprio método, mas podemos fazer separadamente com um método qualquer. Vamos ver isso mais para frente.

Agora vamos conhecer a função Find() e FindAll(). A diferença entre as duas é bem simples. O Find() busca na lista, crescente, um resultado válido, caso encontre, ele para de buscar e retorna um resultado. Em contraponto o FindAll() procura por todos valores da lista e retorna uma outra lista de resultados válidos.

Vamos estudar o método Procura.

private static void Procura(List<Pessoa> lstPessoas)
{
    //Função Find retornando uma pessoa pelo Nome
    Pessoa pessoa = lstPessoas.Find(PorNome);
    Console.WriteLine(
        pessoa != null ? 
            "Pessoa Encontrada (No Find): " + pessoa.Nome + ", " + pessoa.Idade + ", " + pessoa.Sexo : 
            "Nenhuma pessoa Encontrada");

    //Função FindAll retornando uma lista de pessoas pelo Sexo
    foreach (Pessoa pessoaLocal in lstPessoas.FindAll(PorSexo))
    {
        Console.WriteLine("Pessoa Encontrada (No FindAll): " + pessoaLocal.Nome + ", " + pessoaLocal.Idade + ", " + pessoaLocal.Sexo);
    }

    Console.WriteLine("\n");
}

Este método começa utilizando a função Find da lista genérica. Assim como o método anterior, passamos a lista carregada.

Criamos um objeto pessoa, pois já sabemos que o Find retorna um resultado único. Podemos notar que não é utilizado o delegate, entretanto o Find também espera um System.Predicate.

Isto porque, agora chamamos direto um método, o PorNome.

private static bool PorNome(Pessoa pessoa)
{
    if (pessoa.Nome == "Adriano Galesso")
    {
        return true;
    }

    return false;
}

O método PorNome retorna um boleano (como dito anteriormente). E recebe uma pessoa, mas como isso se não passamos nada na chamada do método?

Como o predicate é tipado, automaticamente se sabe que objeto você está tentando procurar. Então no parâmetro do método é passado o objeto da lista (funciona como um foreach).

No método PorNome simplesmente fazemos uma validação qualquer e retornamos ao método Procura. Que verificará se o objeto pessoa não esta nulo e escrever que foi encontrado na lista.

Continuando no método Procura. Agora vamos utilizar a função FindAll() da lista genérica. Como já sabemos teremos uma lista de resultados, pois ele irá procurar em todos objetos da lista. O predicate que utilizaremos é o método PorSexo.

private static bool PorSexo(Pessoa pessoa)
{
    if (pessoa.Sexo == 'F')
    {
        return true;
    }

    return false;
}

Nada de diferente neste método, simplesmente vamos procurar em nossa lista todas as mulheres.

Voltando novamente no método Procura, como temos uma lista de resultados vamos usar o foreach para escrever os resultados com sucesso de nossa lista.

Por fim, vamos ver o método Remove.

private static void Remove(List<Pessoa> lstPessoas)
{
    lstPessoas.Remove(new Pessoa("Adriano Galesso", 23, 'M'));

    lstPessoas.RemoveAll(Jovens);

    foreach (Pessoa pessoa in lstPessoas)
    {
        Console.WriteLine("Velhos: " + pessoa.Nome + ", " + pessoa.Idade + ", " + pessoa.Sexo);
    }

    Console.WriteLine("\n");
}

Como anteriormente, passamos nossa lista de pessoas como parâmetro. Inicialmente usamos a função Remove da lista genérica. Que não tem nada de novo, simplesmente passamos um objeto que gostaríamos de remover e pronto, nada de predicate.

Depois disso vamos Remover todos os Jovens da Lista com o RemoveAll. Assim como o FindAll teremos uma lista de resultados. A única diferença é que uma vez removido da lista, não poderemos mais encontrar o objeto removido. (Por exemplo, como a lista é por referencia de memória, se chamássemos o método Remove antes dos outros, nossa lista estaria com menos objetos).

Utilizaremos como predicate o método Jovens.

private static bool Jovens(Pessoa pessoa)
{
    if (pessoa.Idade <= 30)
    {
        return true;
    }

    return false;
}

Vamos remover da lista, todas as pessoas com menos de 30 anos. Voltando ao método Remove, escrevemos a lista com os novos resultados.

Por fim, o mais legal das “buscas” em listas genéricas são os predicates. Mas ainda fica uma dúvida no ar. E se eu quiser passar mais parâmetros para um método delegate?

Bom, tem como, mas não fique todo felizão como eu fiquei quando descobri. Primeiro saiba que isso só é possível a partir do Framework 3.5 (meu projeto era no 2.0 =/).

Primeiramente se estivermos usando o Framework 3.5, podemos utilizar os Lambda Expression. Lambda Expression é a evolução dos delegates com pequenas notações, ou seja, se for só para retornar um valor simples, como por exemplo:

Método:
Double MultiplicaPorCinco(int x)
{
    return x * 5;
}

Lambda Expression:
x => x * 5;

Vamos aplicar no método Remove:

private static void Remove(List<Pessoa> lstPessoas)
{
    //lstPessoas.Remove(new Pessoa("Adriano Galesso", 23, 'M'));

    lstPessoas.RemoveAll(pessoa => pessoa.Idade <= 30);

    foreach (Pessoa pessoa in lstPessoas)
    {
        Console.WriteLine("Velhos: " + pessoa.Nome + ", " + pessoa.Idade + ", " + pessoa.Sexo);
    }

    Console.WriteLine("\n");
}

Se olharmos acima, veremos que foi substituído, o método Jovem pelo Lambda Expression.

Legal, e os 2 parâmetros na função?

Bom, isso vai ficar para o próximo Post, quando o lixo estiver cheio de Func =P e mais Lambda Expression

Abraços... PS: Recorri a um script para ajustar os códigos, é bem mais fácil =)

Deletado em 23 de maio de 2010

Recuperando QueryStrings com TryParse

Ultimamente tenho escrito alguns artigos para revistas e sites de tecnologia e a lixeira acaba ficando um pouco vazia.

Entretanto, sempre tem alguma coisa velha que é uma boa nova idéia. Digo velho porque recuperar QueryStrings e variáveis de Sessão em C# até minha tia vó já sabe fazer. Mas será que ela faz da melhor maneira?

Imaginado minha Query String “teste”. “Teste” sempre será a identificação de um elemento que eu gostaria de passar pelas páginas. E outra, eu sei que “teste”  é um inteiro.

Como recuperar?

int meuTeste = Convert.ToInt32(Request.QueryString["teste"]);

Isso é realmente fácil (minha tia vó que postou). Agora vamos falar pra minha tia vó que infelizmente o mundo não é perfeito e podemos ter engraçadinhos que tentam trocar o valor da QueryString manualmente (eu sou um deles). Por Exemplo, colocar um “teste=a” na URL.

Neste ponto minha tia vó sai de cena, isso ela já não sabe. Vamos ser espertos e colocar um Try pra pegar esses engraçadinhos. Mas não podemos ter um Try sem Catch e também não podemos parar a execução da página só porque temos uma variável sem valor (só se a página inteira for em torno desse valor). Neste caso então, vamos verificar se existe o valor da variável na Sessão “teste”, quem sabe o valor não está lá dentro!

int meuTeste = 0;

try
{
    meuTeste = Convert.ToInt32(Request.QueryString["teste"]);
}
catch
{
    meuTeste = Convert.ToInt32(Session["teste"]);
}

Legal, mas e sem não existir QueryString e não existir a Sessão? Minha página às vezes tem essa QueryString e às vezes tem essa Sessão? Vamos aninhar os Trys ai nos Catches nós pegamos zero da variável bla bla bla bla...

Nada disso. Esquece todos os códigos postados até aqui, pois para resolver qualquer problema para recuperar QueryString ou Sessão de tipos nativos devemos usar o TryParse. Digo devemos porque não há o que fazer se o valor que tentamos atribuir à uma variável não for de um tipo valido para mesma, assim evitamos exceções e obtemos valores válidos em qualquer tipo de ambiente.

Como não gosto de ficar sozinho em uma opinião, tenho dois link que além de me defenderem, eles fazem testes de desempenho entre o parse e o TryParse

http://www.informit.com/guides/content.aspx?g=dotnet&seqNum=523

http://www.codinghorror.com/blog/2005/08/tryparse-and-the-exception-tax.html

Entretanto a questão deste post não é escrever sobre conversões de tipos e sim recuperar valores de QueryStrings ou Sessões. Então, como fazer isso de maneira limpa e prática.

Vamos voltar ao mesmo cenário onde a variável de QueryString “teste” pode existir ou não em uma página, assim como a Sessão “teste” pode existir ou não. Lembro também que não podemos esquecer de testar se o valor da QueryString é um inteiro e não vai me jogar uma exceção.

Chegamos as seguintes linhas de código:

int meuTeste = 0;

if (!int.TryParse(Request.QueryString["teste"], out meuTeste))
{
    int.TryParse(Session["teste"], out meuTeste);
}

O código diz que, se não for convertido a QueryString “teste” para minha variável de saída, que é um inteiro, ele tentará converter a Sessão “teste”. Não vamos verificar se ele consegue converter a Sessão, pois se não o valor da variável vai ser 0 de qualquer maneira.

E porque não usar o Convert.ToInt32? Justamente porque vamos ter que ficar testando os valores pra ver se realmente é um inteiro. E fazer esse processo deixa o código cheio e “chato”.

Por fim, podemos fazer o TryParse além de inteiros, em Decimal, DateTime, Float ou Double.

Até a próxima!

Deletado em 19 de maio de 2010

Um pouco de usabilidade

Após a publicação do Blog do meu amigo Tadanori sobre usabilidade, mais precisamente voltado à e-Commerce, achei essa imagem na net que diz muito sobre a realidade de uma empresa e como cada membro de uma determinada equipe tem uma opnião sobre como deve ser a usabilidade de um site.

De acordo com Jakob Nielsen, o maior análista de usabilidade atualmente, dono do lindo site http://www.useit.com/, pesquisas de usabilidade ajudam muito na modo de como um site pode ou não fazer sucesso na Web. Ou seja, usabilidade terá mais espaço aqui na Lixeira futuramente.

Deletado em 25 de janeiro de 2010

Férias

Olá pessoal, desculpe a falta de lixo neste dias que se passaram. Depois de 2 anos eu tirei minhas férias! \o/

Bom, este ano, vou voltar com a parte de padrões de projeto e outros assuntos que vão bomabar a lixeira.

Topo