Maneira Fácil de Realizar uma Busca Dinâmica com SQL e Stored Procedure

21 05 2010

Boa tarde,

Hoje nesse post será mostrado como construir uma Stored Procedure para a realização de uma Busca Dinâmica. Buscas Dinâmicas são necessárias quando o usuário pode preencher ou não os campos de um formulário no qual é gerado um resultado de busca.

Suponhamos que um formulário contenha os campos Nome, Sobrenome e CPF para a busca de Clientes de uma Loja.

Na Stored Procedure, vamos declarar as variáveis:

CREATE PROCEDURE  SP_BuscaUsuario (@Nome varchar(30) =null, @Sobrenome varchar(50) =null, @Cpf varchar(14) =null)

AS

BEGIN

SELECT  *

FROM Clientes

WHERE
    Nome = COALESCE(@Nome,Nome) AND
Sobrenome = COALESCE(@Sobrenome,Sobrenome) AND
    CPF = COALESCE(@Cpf,CPF)
END

GO

A função COALESCE() do SQL retorna a primeira expressão não-nula que está contida nela.
Por Exemplo:


DECLARE @Expressao1 varchar(30),
@Expressao2 varchar(30)
SET @Expressao1 = NULL
SET @Expressao2 = 'SQL Server'
SELECT COALESCE(@Expressao1,@Expressao2)

--Resultado--
SQL Server

DECLARE @Expressao1 varchar(30),
@Expressao2 varchar(30)

SET @Expressao1 = 'Programeiro'
SET @Expressao2 = 'SQL Server'
SELECT COALESCE(@Expressao1,@Expressao2)

--Resultado--
Programeiro

Sempre que for utilizar algum campo que seja Nullable na Stored Procedure, recomenda-se que atribua o valor null para a variável.

O Coaslece é uma boa alternativa para evitar o comando OR no SQL, o que otimiza bastante o tempo de execução da query.

Espero que isso ajude.

Anúncios




Validando inputs com jQuery e pouco código

11 02 2010

Solução rápida pra validar campos que não podem ser nulos.

Aqui o html com vários inputs type text esperando validação.

<div id=”stepOneContainer” >
<input type=”text” id=”country”/>
<input type=”text” id=”city”/>
<input notNull=”true” id=”mobilePrefix” style=”width : 10px;” />
<input notNull=”true” type=”text” id=”mobile”/>
<input notNull=”true” type=”text” id=”phonePrefix” style=”width : 10px;” />
<input notNull=”true” type=”text” id=”phone” />
<input notNull=”true” quickInfo=”{Global.CPF}” type=”text” id=”cpf” />
<input type=”text” id=”specialities” style=”width : 600px;” />
<input type=”text” id=”abilities” style=”width : 600px;” />
<input type=”text” id=”aboutTitle” style=”width : 600px;” />
<input type=”text” id=”about” style=”width : 600px;” />
<input type=”button” id=”save” />
</div>

Dentro de um determinado container pegamos todos os input text e verificamos se ele contém o atributo notNull == true e o valor nulo. Cada campo que não corresponder a essa validação ficará com a borda vermelha.

easy business =]
$("#stepOneContainer").find("input").each(function() {
var target = $( this );
if (target.attr("notNull") == "true" && target.val().length == 0 ) {
allValidated = false;
target.css("border", "solid 1px red");
}
});




Ordenando array de objetos em javascript

6 01 2010

Desenvolvendo um sistema de search para meu projeto atual me deparei com o problema de fazer um controle de opcoes avançadas sem ter que ficar fazendo inúmeros requests ao servidor.

O search básico seria por uma palavra chave e partir dessa busca os resultados poderiam ser filtrados mais e mais.

Ex >  uma busca de funcionários que contenham a palavra chave “jo”

e o resultado fosse o seguinte

Nome Idade Sexo Contratado em
Joao da Silva 28 M 10/9/2000
Jonata Ferreira 24 M 12/9/2000
Alan Joaquim 22 M 14/9/2000
Joana Silva 21 F 14/9/2000

e partir desse resultado poderíamos filtrar por idade, sexo ou por data de contratação. Mas como fazer essas novas filtragens sem novos requests ao servidor?

Foi então que me deparei com uma ferramenta que serviria exatamente para resolver meu problema. Linq para javascript

home page : http://linqjs.codeplex.com/

Tudo resolvido, eu podia então filtrar os dados da forma que eu quisesse antes de renderiza-los, e apenas com um request ao servidor. Resolvido ate que fui tentar ordenar os resultados e descobrir que o método OrderBy dessa biblioteca nao esta funcionando.

E essa foi minha solução para a ordenação do resultado após ser filtrado.

// data       : array de objetos para ser ordenado
// orderField : campo pelo qual desejamos ordenar
function MyOrderBy( data, orderField ) {
var tempArray = new Array();

var order = new Array();

// Aqui entamos preenchendo o array temporario com os dados do campo
// selecionado (orderField) na ordem exata do primeiro array
for ( var i = 0 ; i < data.length ; i ++ ) {
// try catch serve apenas para garantir que vai funcionar para inteiros e strings
try {
tempArray.push(eval("data[" +  i  + "]." + orderField).toLowerCase());
} catch ( ex ) {
tempArray.push(eval("data[" +  i  + "]." + orderField));
}
}

// Aqui nós estamos ordenando o array de forma crescente
// método sort é nativo do javascript ( embora eu so tenha descoberto ele quando fui fazer esse order by ) =P
// se desejasemos fazer um orderByDescending seria necessario passar passar um outro metodo como parametro para o sort
tempArray = tempArray.sort();

// aqui estamos relacionando o array temporario com o array original e preenchendo
// um terceiro array com as posições dos items conforme o array temporario já ordenado
// EX: a posição 1 do array ordenado correpponde so item 6 do array original
// EX: a posição 2 do array ordenado correpponde so item 1 do array original
// e assim por diante
for ( var i = 0 ; i < tempArray.length ; i ++ ) {
for ( var j = i ; j < tempArray.length ; j ++ ) {
var item;

try {
item = eval("data[" +  j  + "]." + orderField).toLowerCase();
} catch ( ex ) {
item  = eval("data[" +  j  + "]." + orderField);
}

if ( tempArray[i] == item )  {
order.push(j);
}
}
}

var result = new Array();

// agora eh so criar um novo ( e último ) a array e preenche-lo com os dados
// do array original mas na ordem correta
for ( var i = 0 ; i < tempArray.length ; i ++ ) {
result.push(data[order[i]]);
}

return result;
};




Organic Search

22 12 2009

Segundo a Serasa Experian Hitwise, são feitas diariamente no Brasil mais de 200 milhões de pesquisas na internet, e dentro dessas mais de 95% são feitas pelo Google.

Por conta disso o Google tem mais de 1,5 milhões de Adwords, que são anúncios patrocinados vendidos em forma de leilão, o que torna muito caro seu uso.

Para se beneficiar das vantagens de ser visto pelos mecanismos de busca é necessário se ter um site desenvolvido adequadamente, e seguir o guia de otimização de search engine da Google é uma das melhores formas de se conseguir isso.

download

Esse guia de otimização se search engine expõe alguns pontos importante:

  • Criar um título único para cada página em seu site, que descreva exatamente seu conteúdo.
  • Use meta tags de descrição “description”.
  • Organizar a estrutura das urls, deixando-as mais “amigáveis”.
  • Torne seu site navegável. Isso ajuda o sistema de busca a descobrir qual conteúdo é mais importante.
  • Use os textos dos links o mais indescritíveis possível.
  • Use tags de importância <h1> <h2> de forma adequada.
  • Preencha o valor alt das imagens com textos explicativos sobre ela.
  • Promova seu site por outros meios na internet. Vale a pena dar atenção as redes sociais relacionadas a seu negócio.

Esses dois resultados foram os melhores de nosso blog no google, nada muito significativo ainda. Precisamos melhorar isso, promovendo ele de alguma forma.

Mas acho melhor esperar até termos algum conteúdo. =P





Feeds RSS e Atom no .NET

15 12 2009

Símbolo de Feed

Símbolo de Feed

Arquivos Feeds são listas de atualização de conteúdo de um determinado site, escritos nas especificações do padrão XML. Seu nome provém do inglês e significa alimentar, em alusão ao seu modo de utilização.

Feeds são um recurso indispensável em qualquer Website que forneça atualizações fequentes de conteúdo, pois possibilita que os leitores serem informados automaticamente sobre novas atualizações no site, sem a necessidade de realizar visitas periódicas para verificar se há novas informações disponíveis.

Sua utilização pode ser útil em sites com grandes quantidades de atualizações em seus conteúdos.

Atualmente, existem 3 padrões estabelecidos para a criação de feeds:

  • RSS 1.0 – RDF Site Summary 1.0 (RSS-DEV).
  • RSS 2.0 – Really Simple Syndication 2.0 (Userland).
  • Atom (IETF)

Neste post serão abordados os 2 padrões mais utilizados hoje em dia, o RSS 2.0 e o Atom 1.0. O Atom é o mais recente e veio para preencher as lacunas do RSS, porém seu objetivo é o mesmo do RSS: prover atualizações em um formato pré-definido. Para o usuário não existem grandes diferenças entre o uso do RSS ou do Atom.

Para a criação de feeds RSS ou Atom no .NET Framework 3.5 é necessária a utilização da  Biblioteca Syndication, no namespace System.ServiceModel.Syndication, que possui as classes necessárias para a criação de feeds RSS ou Atom.

Partindo do zero, será criado um projeto com o objetivo de publicar um feed para qualquer site. O projeto será criado no Visual Web Developer 2008. Será utilizado também Sql Server para o banco de dados e LINQ To Entities para manipulação dos dados.

Será necessário fazer o download do WCF REST Starter Kit. Para baixá-lo, clique aqui. Para a execução deste exemplo, é necessário possuir o Service Pack 1 do Visual Studio 2008. Caso você não possua, clique aqui para baixá-lo.

Com tudo instalado, vamos criar um projeto utilizando o template Atom Feed WCF Service ,como na imagem a seguir:

Criando Projeto Atom Feed WCF Service

Figura 01 - Criando Projeto Atom Feed WCF Service

A partir do projeto criado, podemos criar uma base de dados para armazenar as informações dos feeds. Para isso, basta clicar com o botão direito na pasta App_Data > Add > New Item  > SQL Server Database.

Criação do Banco de Dados AtomFeed

Criação do Banco de Dados AtomFeed

Clique no arquivo .mdf e com isso irá abrir no canto esquerdo a janela Server Explorer. Expanda o arquivo .mdf , clique com o botão direito em Tables > Add New Table. Crie uma tabela no seguinte padrão:

Criação da Tabela Feed

Salve o projeto. ele irá pedir pra nomear a tabela. No exemplo foi usado o Nome Feed. Para facilitar o acesso aos dados, será utilizado LINQ to Entities. Em uma próxima ocasião abordaremos com mais detalhes um artigo sobre LINQ e Entity Data Model.

Adiciona-se então um novo projeto com o template ADO.NET Entity Data Model, conforme figura abaixo:

Adicionando projeto ADO.NET Entity Data Model

Adicionando projeto ADO.NET Entity Data Model

Ao adicionar, irá abrir um Assistente para auxiliá-lo. Selecione então a opção Generate from Database:

Criação do Entity Data Model

Criação do Entity Data Model

Agora selecione a base de dados criada anteriormente, dessa maneira:

Configurando o Entity Data Model

Configurando o Entity Data Model

Selecionando a Base de Dados

Selecionando a Base de Dados

Assim,  é feito um mapeamento da tabela Feed automaticamente. São criados novos arquivos: AtomFeedModel.edmx e Service.svc, este ultimo criado automaticamente contendo a classe FeedService e o método GetFeed. O método já possui a lógica para geração de um feed Atom.  Porém, vamos utilizar outra lógica. Então, substitua o conteúdo do método GetFeed pelo bloco abaixo:

if (i &lt; 0) throw new WebProtocolException(HttpStatusCode.BadRequest, "numItems cannot be negative", null);
if (i == 0) i = 1;

// Estanciando objeto Feed e setando suas propriedades

SyndicationFeed feed = new SyndicationFeed("Feed", "Exemplo de Feed",
new Uri("http://exemplo.com/feed"));
feed.Id = "http://exemplo.com/feed";
feed.Copyright = new TextSyndicationContent("Copyright ® 2010 Programeiro");
feed.Authors.Add(new SyndicationPerson("hsalvs@gmail.com", "Heitor", string.Empty));
feed.Language = "pt-BR";

//Lista contendo os feeds, criados de acordo com o banco de dados
List items = new List();

//Agora será utilizado LINQ to Entities.
//Acessando a base de dados para obter informações necessárias

using (AtomFeedEntities entities = new AtomFeedEntities())
{
var query = from item in entities.Feed
orderby item.DataCriacao descending
select item;

/*O LINQ não permite que um construtor com parêmetros seja chamado no 'select',
* então é preciso iterar cada item para criar o respectivo SybdicationItem */

foreach (var item in query)
{
/*Para cada item da base de dados criamos um SyndicationItem com
as respectivas propriedades*/
SyndicationItem syndicationItem = new SyndicationItem();
syndicationItem.Id = item.ID.ToString();
syndicationItem.Title = TextSyndicationContent.
CreatePlaintextContent(item.Título);
syndicationItem.Content = TextSyndicationContent.
CreateHtmlContent(item.Descricao);
syndicationItem.PublishDate = item.DataCriacao;
syndicationItem.AddPermalink(new Uri(string.Format("http://exemplo.com/item/{0}", syndicationItem.Id)));

//Agora adicionamos na lista
items.Add(syndicationItem);
}
}

//Atribui-se a lista ao feed, limitando ao número de itens especificado atraves da variavel numItems
feed.Items = items.Take(i);

WebOperationContext.Current.OutgoingRequest.ContentType = ContentTypes.Atom;

return new Atom10FeedFormatter(feed);

O método GetFeed possui um parêmetro que recebe o número de itens desejados pelo usuário naquele acesso. Foi aproveitada a mesma lógica de tratamento desse parâmetro do templete padrão. Após isso foi instanciada a classe SyndicationFeed e foram setadas as propriedades com as informações do feed contido no banco de dados. Em seguida, é populada uma lista de SyndicationItems que serão as atualizações do feed. No final, atribui-se a lista de items ao SyndicationFeed, limitando de acordo com a variavel numIrems e após isso é retornado um Atom10FeedFormatter baseado no nosso feed. A própria classe aplica a formatação definida para o padrão Atom 1.0, portanto é uma coisa a menos para se preocupar.

Popule o banco de dados que foi criado e depois verifique as informações no browser. Clique no item Service.svc para visualizar os resultados. Neste caso ele mostrará apenas o primeiro feed do banco porque a variável numItems equivale a 1.

Resultado no Firefox

Resultado no Firefox

O XML gerado pelo fica assim:


<feed xml:lang="pt-BR" xmlns="http://www.w3.org/2005/Atom">
 <title type="text">Feed</title>
 <subtitle type="text">Exemplo de Feed</subtitle>
 <id>http://exemplo.com/feed</id>
 <rights type="text">Copyright ® 2010 Programeiro</rights>
 <updated>2009-12-15T20:25:53Z</updated>
 <author>
   <name>Heitor</name>
   <email>hsalvs@gmail.com</email>
 </author>
 <link rel="alternate" href="http://exemplo.com/feed"/>
 <entry>
   <id>http://exemplo.com/item/1</id>
   <title type="text">Teste</title>
   <published>2009-12-15T00:00:00-02:00</published>
   <updated>2009-12-15T20:25:53Z</updated>
   <link rel="alternate" href="http://exemplo.com/item/1"/>
   <content type="html">Um teste de Atom</content>
 </entry>
</feed>

Agora para deixar esse código flexível, possibilitando a geração de feeds RSS e Atom, é fácil.
Precisamos apenasadicionar um novo parâmetro para informar o formato desejado e utilizar uma classe mais genérica apara que seja possível ao método entregar tanto RSS quanto Atom.
Além disso, vamos adicionar o atributo ServiceKnownTypeAttibute informando os tipos Rss20FeedFormatter e Atom10Formatter ao método, já que estes serão os dois tipos retornados pelo nosso método.
A assinatura ficará assim:

[WebHelp(Comment = "Sample description for GetFeed.")]
 [WebGet(UriTemplate = "?numItems={i}&format={format}")]
 [ServiceKnownType(typeof(Rss20FeedFormatter))]
 [OperationContract]
 [ServiceKnownType(typeof(Atom10FeedFormatter))]
 public SyndicationFeedFormatter GetFeed(int i, string format)

Foi alterada a assinatura do método GetFeed, adicionando a variável format, para que se estabeleça o padrão de retorno do feed. O tipo de retorno foi alterado para SyndicationFeedFormatter.
Portando, o retorno do método GetFeed ficará assim

if (format.ToLower() == "rss")
 return new Rss20FeedFormatter(feed, false);

 return new Atom10FeedFormatter(feed);

Agora vamos consumir um feed. Primeiramente,  adicionamos um Web Form ao projeto. O chamarei de Consumidor.aspx. Agora colocamos dois Labels e um DataList.

No arquivo .aspx , precisamos alterar o ItemTemplate do DataList para que seja possível exibir o conteúdo do feed. Então, substituímos o código do DataList pelo seguinte código:

<asp:DataList ID="DltFeed" runat="server">
<ItemTemplate>
<asp:HyperLink ID="hplFeed" runat="server" Text='<%# Eval("Title.Text")%>’ Font-Bold="true"
NavigateUrl='<%# Eval("Links[0].Uri.AbsoluteUri") %>’></asp:HyperLink>
<br />
<asp:Label ID="lblTexto" runat="server" Text='<%# Eval("Summary.Text") %>’></asp:Label>
</ItemTemplate>
</asp:DataList>

E no CodeBehind, dentro do método Page_Load devemos colocar:


using System.Xml;
using System.ServiceModel.Syndication;
...
 protected void Page_Load(object sender, EventArgs e)
 {
    XmlReader reader = XmlReader.Create("http://blogs.iis.net/rawmainfeed.aspx");
    Rss20FeedFormatter fmt = new Rss20FeedFormatter();
    fmt.ReadFrom(reader);
    reader.Close();
    Label1.Text = fmt.Feed.Title.Text;
    Label2.Text = fmt.Feed.Description.Text;
    DltFeed.DataSource = fmt.Feed.Items;
    DltFeed.DataBind();
 }

Utilizamos o Rss2.0 para ler o conteúdo do feed via HTTP e então a classe Rss20feedFormatter para interpretá-lo. Essa classe é responsável por realizar todo o ‘trabalho sujo’, pois todo o trabalho que temos é o de chamar o método ReadFrom(). Caso o feed a ser lido fosse Atom, a única alteração seria o uso da classe Atom10FeedFormatter no lufar da Rss20FeedFormatter.

O resultado é esse:

Leitor de Feeds

Leitor de Feeds

Fontes:





AJAX, .NET e JQuery

9 12 2009

AJAX

AJAX é uma abreviatura para “Asynchrounous Javascript and XML” e consiste em uma combinação de tecnologias web trabalhando em conjunto. Essa não é uma técnica nova mas sua implementação era difícil até a chegada do framework JQuery, que nos fornece ferramentas muito úteis no desenvolvimento web com AJAX.

É uma técnica que muda a forma (e o tempo) de resposta as interações do usuário, tornando dispensáveis muitos “refresh” nas páginas e deixando a interação com o usuário muito mais atraente e agradável.

Na imagem acima podemos ver o que diferencia uma aplicação web convencional e uma aplicação web utilizando AJAX. A aplicação com AJAX faz pequenos requests via javascript e recebe os dados em formato xml ou JSON, sem a necessidade de recarregar a página.

Imagine o seguinte cenário:

Temos uma galeria de fotos qualquer, com uma paginação normal e onde podem ser exibidas 4 fotos por vez.
Toda vez que paginarmos essa galeria uma função em javascript será acionada e fará uma requisição ao servidor (sem recarregar a página). O servidor enviará os novos dados, que no caso são as fotos referentes a nova página e então será necessário um pouco mais de javascript para para limpar as fotos da pagina anterior, criar novos objetos (DOM) e renderiza-los na página.

Vantagens

  • reduz o número de conexões e com o servidor já que html, css e javascript são carregados apenas uma vez
  • reduz o tempo de carregamento, o usuário não fica recarregando a página várias vezes.
  • Melhora a experiência do usuário.

Contratempos

  • Se torna um pouco mais difícil debugar (embora existam ferramentas bastante boas para isso) e encontrar alguns problemas durante o desenvolvimento.
  • Necessário suporte a javascript no navegador (acredito que nem chegue a ser um problema atualmente) .

Desenvolvimento .NET, C# e AJAX

Server side:

Uma forma de se responder os requests feitos pelo javascript é com uma página ou handler que executa a lógica de negócios e retorna o resultado no response.

Outra maneira (que considero melhor e mais rápida) é fazer requests para um método dentro de um webservice. Nota: esse webservice deve estar na mesma aplicação da chamada de javascript, caso contrário você terá problemas de permissão. Lembre-se também de colocar esse header no seu webService [System.Web.Script.Services.ScriptService] para que as chamadas de javascript sejam aceitas.

Client side:

Como dito anteriormente um ótimo modo de fazer chamadas AJAX em javascript é usando JQuery, usando o método JQuery.ajax :

Example:

$.ajax({
      url: "teste.asmx/MeuMetodo",
      type: "POST",
      data: ({"nomeDoParametro" : "valor do parametro"}), // parametros em formato json
      dataType: "html", // pode ser json ou xml também
      success: function(msg){
         // aqui é o método executado quando a resposta é enviada do servidor
         alert(msg);
      }
   });

Após o retorno dos dados do servidor só é necessário brincar um pouquinho mais com javascript renderizar a página de forma correta.

Exemplo:

Usando o exemplo da galeria de fotos

Nosso método de webService

[WebMethod]
public object GetPhotos(int pageIndex)
{
// suponhamos que esse método retorne sempre 4 elementos
// então nós criamos um objeto anônimo que é perfeitamente serializável para o formato JSON
return
from result in PhotosBussines.GetGallery(pageIndex)
select new
{
Image = result.image
}
}
Nosso método de javascript
$.ajax({
      url: "http://localhost:12345/services/photos.asmx/GetPhotos", // imagine que esse método retorna um array de 4 posições com as urls das fotos
      type: "POST",
      data: ({"pageIndex" : 2), // estamos indo para a pagina 2
      dataType: "json",
      success: function(data){
         $("#Image1").attr("src", data[0].Image);
         $("#Image2").attr("src", data[1].Image);
         $("#Image3").attr("src", data[2].Image);
         $("#Image4").attr("src", data[3].Image);
      }
   });
E temos nosso próprio AJAX  funcionando com a ajuda do JQuery.

Links úteis :





Início

4 12 2009

Bom,

Hoje o blog Programeiro inicia suas atividades.

Um blog relacionado com a parte de programação de sistemas, tanto web quanto desktop.

O nosso intuito é divulgar dicas sobre programação, melhores práticas de desenvolvimento de sistemas, etc. , sempre focando no que acontece realmente na hora de por a mão na massa.

Também estaremos atentos às novidades do nosso mundo.

E é claro, as postaremos aqui nesse espaço também.

Desejamos que nossos post ajudem e informem a todos.

Muito Obrigado.