Array
(
)

Contagem de novas mensagens dinamicamente

Hernane Goncalves
   - 06 set 2011

Bom galera, estou com uma duvida terrível.   quero fazer uma contage de menssagens novas no meu banco de dados e jogar na tela do usuário para que ele faça a requisição de visualização dessas novas mensagens.   é tipo o que existe hoje nas caixas de e-mail, onde tem a caixa de entrada e o (numero de mensagens novas) que atualiza toda vez que recebe uma.   mas isso tem que ser de forma dinamica, sem precisar da um postback na pagina, um bom exemplo é a pagina do twiter, quando alguém manda uma nova mensagen, aparece na caixa o numero de mensagens novas que tem para a pessoa ler, e quando voce clica la as mensagens aparecem na tela.   quero saber qual é a solução utilizada para fazer isso (xml, java script, ajax, comet etc). uma solução que nao sobrecarregue tanto o servidor.     desde ja obrigado.

Rodrigo Odasaki
   - 06 set 2011

Você cria um UpdatePanel para fazer as contagem dos números de registros..
Utiliza um timer para fazer a requisição de tanto em tanto tempo.

As mensagens(registros) que o usuário abrir você invoca no evento init para salvar na coluna como lida, colocando como true. Se ela não foi lida por padrão nasce como false.

Rodrigo Odasaki
   - 06 set 2011

Como você falou, postback, então deve ser web forms mesmo que você está utilizando.

Hernane Goncalves
   - 07 set 2011

mas este método estressaria muito o servido não ? imagine esta aplicação com milhares de usuários tendo que consultar o banco por exemplo de 10 em 10 segundos para fazer esta contagem ou esta consulta não pesaria tanto no banco ?

Rodrigo Odasaki
   - 10 set 2011

A consulta sempre vai ter, pois é necessário realizar a consulta automaticamente. Porém o único dado a ser retornado será a contagem total das mensagens.

O que você pode fazer é otimizar essa consulta utilizando Ajax para realizar uma chamada assíncrona no servidor somente da área a qual você deseja, no caso a contagem.

 

Hernane Goncalves
   - 10 set 2011

sem querer abusar muito da sua boa vontade, teria como você da um exemplo de código de como eu faria isso: "chamada assíncrona no servidor somente da área a qual você deseja, no caso a contagem."?

Rodrigo Odasaki
   - 11 set 2011

Veja:

Tabelas:

Default.aspx

O ScrpitManager no topo é responsável por realizar as chamadas assíncronas com o servidor.
Dentro do container ContentTemplate você vai colocar os dados que deseja atualizar.
No Timer será responsável por realizar a chamada de tanto em tanto tempo, a propriedade Interval é responsável por isso e ela trabalha em milisegundos. No caso no exemplo acima está de 5 em 5 segundos.
A Trigger informa que o PostBack para o controle Timer é assíncrono.

Na label countMsgLabel recebe a contagem total de todas as mensagens para este usuário.

Na página Default.aspx.cs 

Para não ter erro fiz o exemplo com ADO.NET e LINQ TO SQL.
O que você precisa fazer apenas é escolher o método que carrega no page load e no método TimercountMsg_Tick retirando o comentário.
No where eu coloquei o id para simplificar, mas você pode tratar isso de acordo com o usuário que está logado.
Se for usar ADO, eu recomendo você utilizar procedure.

Se tiver dúvida em qualquer linha me avisa.

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;using System.Data;using System.Data.SqlClient;using System.Configuration;using System.Collections;
namespace Devmedia{    public partial class Default : System.Web.UI.Page    {        protected void Page_Load(object sender, EventArgs e)        {            LoadCountMessageWithADO();            //LoadCountMessageWithLINQ();            //LoadCountMessageWithLINQLambda();            //LoadCountMessageWithLINQProcedure();            DateTimeNowForaLabel.Text = DateTime.Now.ToString();            DateTimeNowDentroLabel.Text = DateTime.Now.ToString();          }
        // com ADO.NET
        public void LoadCountMessageWithADO()        {                   SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["Devmedia"].ConnectionString);            string SQL = "Select COUNT(UserId) From UserMessage Where UserId = 1";            SqlCommand cmd = new SqlCommand(SQL, con);            cmd.CommandType = CommandType.Text;            con.Open();            SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);            while (dr.Read())            {                countMsgLabel.Text = dr[0].ToString();            }            }
        // com LINQ        public void LoadCountMessageWithLINQ()        {            DevmediaDataContext db = new DevmediaDataContext();            var dados = from c in db.UserMessages                        where c.UserId == 1                        select c;            int count = dados.Count();            countMsgLabel.Text = count.ToString();            }
        // com LINQ utilizando Lambda Expression        public void LoadCountMessageWithLINQ()        {            DevmediaDataContext db = new DevmediaDataContext();            var dados = db.UserMessages.Where(c => c.UserId == 1).Select(c => c.UserId);            int count = dados.Count();            countMsgLabel.Text = count.ToString();                   }
        // com LINQ utilizando Procedure        public void LoadCountMessageWithLINQProcedure()        {            DevmediaDataContext db = new DevmediaDataContext();            var qualquercoisa = db.SPCountMessageUser();
            foreach (var item in qualquercoisa)            {                countMsgLabel.Text = item.Column1.ToString();            }        }
        protected void TimercountMsg_Tick(object sender, EventArgs e)        {            LoadCountMessageWithADO();            //LoadCountMessageWithLINQ();            //LoadCountMessageWithLINQLambda();            //LoadCountMessageWithLINQProcedure();        }    }}

Rodrigo Odasaki
   - 11 set 2011


Sobre as outras Label eu coloquei para você ver a diferença com um DateTime.Now dentro do UpdatePanel e outro fora.

Insert Into UserMessage (UserId, Resume, Description, Date)VALUES(1, 'Resume of message', 'description of message', GETDATE())

Após o Insert, veja que o conteúdo foi atualizado, porém somente dentro do UpdatePanel.

 

Rodrigo Odasaki
   - 19 out 2011

Eae, conseguiu?

Hernane Goncalves
   - 12 nov 2011

muito bom cara, valew mesmo pela ajuda.