Contagem de novas mensagens dinamicamente
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.
Hernane Goncalves
Curtidas 0
Respostas
Rodrigo Odasaki
06/09/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.
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.
GOSTEI 0
Rodrigo Odasaki
06/09/2011
Como você falou, postback, então deve ser web forms mesmo que você está utilizando.
GOSTEI 0
Hernane Goncalves
06/09/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 ?
GOSTEI 0
Rodrigo Odasaki
06/09/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.
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.
GOSTEI 0
Hernane Goncalves
06/09/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."?
GOSTEI 0
Rodrigo Odasaki
06/09/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(); } }}
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(); } }}
GOSTEI 0
Rodrigo Odasaki
06/09/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.
GOSTEI 0
Rodrigo Odasaki
06/09/2011
Eae, conseguiu?
GOSTEI 0
Hernane Goncalves
06/09/2011
muito bom cara, valew mesmo pela ajuda.
GOSTEI 0