当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > Discuz .net版本中的短消息系统

ASP.NET
赫赫大名的A*寻路算法(vb.net版本)
asp.net(c#)下Jmai去说明 使用与下载
[原创]完美解决Could not load file or assembly ''AjaxPro.2'' or one of its dependencies. 拒绝访问。
asp.net下gridview 批量删除的实现方法
用CSS实现图片倾斜 只支持IE
.net get set用法小结
vs 不显示行号的操作方法
ASP.NET页面进行GZIP压缩优化的几款压缩模块的使用简介及应用测试!(附源码)
ASP.Net不执行问题一解
asp.net 无限分类
让VS2008对JQuery语法的智能感知更完美一点
扩展方法ToJSON() and ParseJSON()
asp.net下PageMethods使用技巧
Linq to SQL Delete时遇到问题的解决方法
实现ASP.NET多文件上传程序代码
ASP.NET AJAX 1.0 RC开发10分钟图解
asp.net get set用法
ASP.NET下使用WScript.Shell执行命令
asp.net2.0实现邮件发送(测试成功)
Asp.net 无限级分类实例代码

ASP.NET 中的 Discuz .net版本中的短消息系统


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-11   浏览: 193 ::
收藏到网摘: n/a

Discuz .net 短消息实现原理。

在Discuz中,消息可以分为公用消息(管理后台 --> 其他 -->公共消息管理)如下:

另外还有批量短消息发送(用户管理):

以及个人用户时的发送:

Discuz .net 短消息实现原理。
而在discuz中,短信息只用到了一张表:dnt_pms
其字段说明如下:
复制代码 代码如下:

pmid:自递增的id
msgfrom:发送者的用户名,若为系统消息则为“系统”。
msgfromid:发送者的id
msgto:接收者的用户名
msgtoid:接收者的id
folder: 0、收件箱,1、发件箱,2、草稿箱
new:是否是新消息,未读,1;0已读
subject:标题
postdatetime:发送时间
message:消息内容

看下公用信息部分的函数:
复制代码 代码如下:

/// <summary>
/// 得到公共消息数量
/// </summary>
/// <returns>公共消息数量</returns>
public int GetAnnouncePrivateMessageCount()
{
return Utils.StrToInt(DbHelper.ExecuteScalar(CommandType.Text, "SELECT COUNT(pmid) FROM [" + BaseConfigs.GetTablePrefix + "pms] WHERE [msgtoid] = 0").ToString(), 0);
}

/// <summary>
/// 获得指定用户的短信息列表
/// </summary>
/// <param name="pagesize">每页显示短信息数</param>
/// <param name="pageindex">当前要显示的页数</param>
/// <returns>短信息列表</returns>
public IDataReader GetAnnouncePrivateMessageList(int pagesize, int pageindex)
{
string sql = "";
if(pageindex <= 1)
{
sql = string.Format("SELECT TOP {0} * FROM [{1}pms] WHERE [msgtoid] = 0 ORDER BY [pmid] DESC", pagesize, BaseConfigs.GetTablePrefix);
}
else
{
sql = string.Format("SELECT TOP {0} * FROM [{1}pms] WHERE [msgtoid] = 0 AND [pmid] < (SELECT MIN([pmid]) FROM (SELECT TOP " + (pageindex - 1) * pagesize + " [pmid] FROM [{1}pms] WHERE [msgtoid] = 0 ORDER BY [pmid] DESC) AS tblTmp) ORDER BY [pmid] DESC", pagesize, BaseConfigs.GetTablePrefix);
}
IDataReader reader = DbHelper.ExecuteReader(CommandType.Text, sql);
return reader;
}

可见:msgtoid=0为判断是否公用信息的条件。
而在注册部分发送一条欢迎的信息到新用户的收件箱中,欢迎信息只有一条,而公用信息可以有很多条,每个注册的用户如果后台设置了发送欢迎消息,则都会执行以下代码:
复制代码 代码如下:

PrivateMessageInfo privatemessageinfo = new PrivateMessageInfo();
string curdatetime = Utils.GetDateTime();
// 收件箱
privatemessageinfo.Message = config.Welcomemsgtxt;
privatemessageinfo.Subject = "欢迎您的加入! (请勿回复本信息)";
privatemessageinfo.Msgto = userinfo.Username;
privatemessageinfo.Msgtoid = uid;
privatemessageinfo.Msgfrom = PrivateMessages.SystemUserName;
privatemessageinfo.Msgfromid = 0;
privatemessageinfo.New = 1;
privatemessageinfo.Postdatetime = curdatetime;
privatemessageinfo.Folder = 0;
PrivateMessages.CreatePrivateMessage(privatemessageinfo, 0);

而其批量发送短消息:

执行方法也是让我感到奇怪,居然是:比如我选择了乞丐,而乞丐这个等级有10万用户,则取得这10W用户的数据,一条条执行插入。暴汗……这样算法以及实现确实简单了很多,但会员一多,要经常清理这些数据。这也是为什么我们看到discuz的论坛经常一段时间需要清理短消息的原因。建议批量发送只对等级较高,数量较少的用户使用。同时在使用过程中,不明白为什么在“批量短消息发送”中的“文件箱”有“收件箱”、“发件箱”、“草稿箱”3种,这里应该只有“收件箱”比较合适,或者这里根本就不该出现这个“文件箱”。
批量发送的代码如下:
复制代码 代码如下:

private void BatchSendSM_Click(object sender, EventArgs e)
{
#region 批量短消息发送
if (this.CheckCookie())
{
string groupidlist = Usergroups.GetSelectString(",");
if (groupidlist == "")
{
base.RegisterStartupScript( "", "<script>alert('请您先选取相关的用户组,再点击提交按钮');</script>");
return;
}
int percount = 10; //每多少记录为一次等待
int count = 0; //当前记录数
// GetUserNameListByGroupid为取得选中的用户组的所有用户的id和用户名
foreach (DataRow dr in DatabaseProvider.GetInstance().GetUserNameListByGroupid(groupidlist).Rows)
{
DatabaseProvider.GetInstance().SendPMToUser(username.Replace("'", "''"), userid, dr["username"].ToString().Replace("'", "''"), Convert.ToInt32(dr["uid"].ToString()), int.Parse(folder.SelectedValue), subject.Text, Convert.ToDateTime(postdatetime.Text), message.Text);
if (count >= percount)
{
Thread.Sleep(3500);
count = 0;
}
count++;
}
base.RegisterStartupScript( "PAGE", "window.location.href='global_sendSMtogroup.aspx';");
}
#endregion
}
//SendPMToUser函数如下:
public void SendPMToUser(string msgfrom, int msgfromid, string msgto, int msgtoid, int folder, string subject, DateTime postdatetime, string message)
{
DbParameter[] parms =
{
DbHelper.MakeInParam("@msgfrom", (DbType)SqlDbType.NVarChar,50, msgfrom),
DbHelper.MakeInParam("@msgfromid", (DbType)SqlDbType.Int, 4, msgfromid),
DbHelper.MakeInParam("@msgto", (DbType)SqlDbType.NVarChar,50, msgto),
DbHelper.MakeInParam("@msgtoid", (DbType)SqlDbType.Int, 4, msgtoid),
DbHelper.MakeInParam("@folder", (DbType)SqlDbType.SmallInt, 2, folder),
DbHelper.MakeInParam("@subject", (DbType)SqlDbType.NVarChar,60, subject),
DbHelper.MakeInParam("@postdatetime", (DbType)SqlDbType.DateTime,8, postdatetime),
DbHelper.MakeInParam("@message",(DbType)SqlDbType.NText, 0,message)
};
string sql = "INSERT INTO [" + BaseConfigs.GetTablePrefix + "pms] (msgfrom,msgfromid,msgto,msgtoid,folder,new,subject,postdatetime,message) " +
"VALUES (@msgfrom,@msgfromid,@msgto,@msgtoid,@folder,1,@subject,@postdatetime,@message)";
DbHelper.ExecuteNonQuery(CommandType.Text, sql, parms);
sql = "UPDATE [" + BaseConfigs.GetTablePrefix + "users] SET [newpmcount]=[newpmcount]+1 WHERE [uid] =@msgtoid";
DbHelper.ExecuteNonQuery(CommandType.Text, sql, parms);
}

有一句语句是用于users用户表中的一个字段,而用户表中有两个字段跟短消息是相关的:
不明白这里为什么要用两个字段,用newpmcount一个字段就可以判断是否有新消息了,如果为0说明没有新消息,而查看消息后也只需要对newpmcount进行操作,并不需要对newpm也进行操作。公用消息并不会对这两个字段进行操作。
详细如下,根据自己见解做了修改,在会员阅读信息之后的具体操作大家应该都清楚,就不写那么仔细。