用Asp.net实现基于XML的留言簿--good
留言簿是网站的一个重要组成部分,是访问者发表意见的场所,也是网站管理员了解网站基本情况的有力工具。所以留言簿在现在的网站中扮演了重要的角色。
可是在以前开发一个留言簿并不是一件容易的事,开发者的工作量往往会很多。而现在随着微软推出VS.net,相应的技术推陈出新。特别是XML在.net Framework中的广泛运用,使得整个.net构架具有十分优越的基础。在VS.net推出的同时,也伴随而来了一门新兴的语言C#。C#作为微软.net战略的重要部分,具有特别优秀的性能。所以本文的asp.net程序是用C#语言描述的,同时整个程序又是基于XML的。我用到了XML作为程序的数据库,主要是因为所以的服务器都是支持XML文件的。
二.要求:
(1) .Net SDK Beta2及以后版本
(2) 支持Asp.net的Web服务器
三.说明:
本文的实例由两部分组成:
(1) guestpost.aspx-将用户信息添加到一个XML文件中
(2) viewguestbook.aspx-先建立一个数据集对象,建立后,就很容易显示其中的数据了。我这里用到了一个“Repeater”来显示数据集中的数据。还有,读者可试着根据自己的喜好来修改查看页。
四.代码:
(1) guestpost.aspx:
< %@ Page Language="C#" EnableSessionState="False" % >
< %@ Import Namespace="System" % >
< %@ Import Namespace="System.IO" % >
< %@ Import Namespace="System.Data" % >
< %-- 这些是本程序正常运用所必须的名字空间 --% >
< html >
< head >
< title >欢迎来到我的留言簿< /title >
< script Language="C#" runat="server" >
///< summary >
/// 当提交(submit)按钮按下后,调要这个函数
///< /summary >
public void Submit_Click(Object sender, EventArgs e)
{
//保存数据的XML文件的路径
//如果你的路径和下面的不同,则请修改之
string dataFile = "db/guest.xml" ;
//运用一个Try-Catch块完成信息添加功能
try{
//仅当页面是有效的时候才处理它
if(Page.IsValid){
errmess.Text="" ;
//以读的模式打开一个FileStream来访问数据库
FileStream fin;
fin= new FileStream(Server.MapPath(dataFile),FileMode.Open,
FileAccess.Read,FileShare.ReadWrite);
//建立一个数据库对象
DataSet guestData = new DataSet();
//仅从数据库读取XML Schema
guestData.ReadXmlSchema(fin);
fin.Close();
//从数据集的Schema新建一个数据行
DataRow newRow = guestData.Tables[0].NewRow();
//用相应值填写数据行
newRow["Name"]=Name.Text;
newRow["Country"]=Country.Text;
newRow["Email"]=Email.Text;
newRow["Comments"]=Comments.Text;
newRow["DateTime"]=DateTime.Now.ToString();
//填写完毕,将数据行添加到数据集
guestData.Tables[0].Rows.Add(newRow);
//为数据库文件新建另一个写模式的FileStream,并保存文件
FileStream fout ;
fout = new FileStream(Server.MapPath(dataFile),FileMode.Open,
FileAccess.Write,FileShare.ReadWrite);
guestData.WriteXml(fout, XmlWriteMode.WriteSchema);
fout.Close();
//隐藏当前的面板
formPanel.Visible=false;
//显示带有感谢信息的面板
thankPanel.Visible=true;
}
}
catch (Exception edd)
{
//捕捉异常
errmess.Text="写入XML文件出错,原因:"+edd.ToString() ;
}
}
< /script >
< LINK href="mystyle.css" type=text/css rel=stylesheet >
< /head >
(2) viewguestbook.aspx:
< %@ Page Language="C#" % >
< %@ Import Namespace="System" % >
< %@ Import Namespace="System.IO" % >
< %@ Import Namespace="System.Data" % >
< %-- 以上是所需的名字空间 --% >
< html >
< head >
< title >欢迎来到我的留言簿< /title >
< script language="C#" runat=server >
//页面下载完毕后,运行这个脚本
public void Page_Load(Object sender, EventArgs e)
{
//包含所有数据的XML文件的路径
//如果你的路径和下面的不同,则请修改
string datafile = "db/guest.xml" ;
//运用一个Try-Catch块完成信息读取功能
try
{
//建立一个数据集对象
DataSet guestData = new DataSet();
//为数据库文件打开一个FileStream
FileStream fin ;
fin = new FileStream(Server.MapPath(datafile),FileMode.Open,
FileAccess.Read,FileShare.ReadWrite) ;
//把数据库中内容读到数据集中
guestData.ReadXml(fin);
fin.Close();
//将第一个表中的数据集付给Repeater
MyDataList.DataSource = guestData.Tables[0].DefaultView;
MyDataList.DataBind();
}
catch (Exception edd)
{
//捕捉异常
errmess.Text="不能从XML文件读入数据,原因:"+edd.ToString() ;
}
}
< /script >
< LINK href="mystyle.css" type=text/css rel=stylesheet >
< /head >
五.总结:
这个程序完成了,相信大家对实现原理以及技巧都有了大致的了解。通过本文,我主要是想向大家展示用XML处理一些数据库问题时的优点:服务器都支持XML文件,而且处理过程相当简洁明了。当然,用XML也有它的不足之处,就是当数据库很大时,解析过程会花费相当长的时间,因此还是要采用大型的数据库系统的。所以,我只想通过此文起到抛砖引玉的作用。
---------------------------------------
using System;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using System.Xml;
using System.IO;
/// <summary>
/// 论坛类别的操作类
/// </summary>
public class BBSManager
{
//定义常量表示字段名称或SQL语句。
private const string SQL_INSERT_BBSINFO = "INSERT INTO bbsinfo VALUES "+
"(@title,@filename,@posttime,@replycount,@lastreplytime, @postuser,@categoryid)";
private const string PARM_BBS_TITLE = "@title";
private const string PARM_BBS_FILENAME = "@filename";
private const string PARM_BBS_POSTTIME = "@posttime";
private const string PARM_BBS_REPLYCOUNT = "@replycount";
private const string PARM_BBS_LASTREPLYTIME = "@lastreplytime";
private const string PARM_BBS_POSTUSER = "@postuser";
private const string PARM_BBS_CATEGORYID = "@categoryid";
private string xmlfilename = "";
public BBSManager()
{
}
/// <summary>
/// 添加论坛的类别
/// </summary>
/// <param name="name">类别名称</param>
/// <param name="des">类别描述信息</param>
/// <returns>添加是否成功</returns>
public bool AddBBSCategory(string name,string des )
{
//使用StringBuild连接字符串比使用“+”效率高很多
StringBuilder strSQL = new StringBuilder();
//创建论坛添加方法的参数
SqlParameter[] newsParms = new SqlParameter[]{
new SqlParameter("@name", SqlDbType.NVarChar,20),
new SqlParameter("@des", SqlDbType.NVarChar,100)};
//创建执行语句的SQL命令
SqlCommand cmd = new SqlCommand();
// 依次给参数赋值
newsParms[0].Value = name;
newsParms[1].Value = des;
//遍历所有参数,并将参数添加到SqlCommand命令中
foreach (SqlParameter parm in newsParms)
cmd.Parameters.Add(parm);
//获取数据库的连接字符串
using (SqlConnection conn = new SqlConnection(SqlHelper.ConnectionStringLocalTransaction))
{
//加载“添加类别”执行语句
strSQL.Append("Insert into BBSCategory values(@name,@des)");
//打开数据库连接,执行命令
conn.Open();
//设置Sqlcommand命令的属性
cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
cmd.CommandText = strSQL.ToString();
//执行添加的SqlCommand命令
int val = cmd.ExecuteNonQuery();
//清空SqlCommand命令中的参数
cmd.Parameters.Clear();
//判断是否添加成功,注意返回的是添加是否成功,不是影响的行数
if (val > 0)
return true;
else
return false;
}
}
/// <summary>
/// 将发帖内容保存到XML文件中的方法
/// </summary>
/// <param name="filename">XML文件路径全名</param>
/// <param name="title">XML文件路径全名</param>
/// <param name="content">XML文件路径全名</param>
/// <param name="user">XML文件路径全名</param>
public void AddXML(string filename,string title,string content,string user)
{
//初始化XML文档操作类
XmlDocument mydoc = new XmlDocument();
//加载指定的XML文件
mydoc.Load(filename);
//添加元素-帖子主题
XmlElement ele = mydoc.CreateElement("title");
XmlText text = mydoc.CreateTextNode(title);
//添加元素-发帖时间
XmlElement ele1 = mydoc.CreateElement("posttime");
XmlText text1 = mydoc.CreateTextNode(DateTime.Now.ToString());
//添加元素-内容
XmlElement ele2 = mydoc.CreateElement("content");
XmlText text2 = mydoc.CreateTextNode(content);
//添加元素-发帖人
XmlElement ele3 = mydoc.CreateElement("postuser");
XmlText text3 = mydoc.CreateTextNode(user);
//添加文件的节点-msgrecord
XmlNode newElem = mydoc.CreateNode("element", "xmlrecord", "");
//在节点中添加元素
newElem.AppendChild(ele);
newElem.LastChild.AppendChild(text);
newElem.AppendChild(ele1);
newElem.LastChild.AppendChild(text1);
newElem.AppendChild(ele2);
newElem.LastChild.AppendChild(text2);
newElem.AppendChild(ele3);
newElem.LastChild.AppendChild(text3);
//将节点添加到文档中
XmlElement root = mydoc.DocumentElement;
root.AppendChild(newElem);
//获取文件路径
int index = filename.LastIndexOf(@"\");
string path = filename.Substring(0, index);
//新文件名
path = path + @"\" + xmlfilename + "file.xml";
//文件创建后必须关闭,否则其他程序无法调用
FileStream mystream =File.Create(path);
mystream.Close();
//保存所有修改-到指定文件中:注意编码语言的选择
XmlTextWriter mytw = new XmlTextWriter(path,Encoding.Default);
mydoc.Save(mytw);
mytw.Close();
}
/// <summary>
///
/// </summary>
/// <param name="title"></param>
/// <param name="filename"></param>
/// <param name="replycount"></param>
/// <param name="categoryid"></param>
public void AddMsg(string title,string user,int categoryid)
{
//使用StringBuild连接字符串比使用“+”效率高很多
StringBuilder strSQL = new StringBuilder();
//获取缓存参数,如果没有,此方法会自动创建缓存列表
SqlParameter[] newsParms = GetParameters();
//创建执行语句的SQL命令
SqlCommand cmd = new SqlCommand();
// 依次给参数赋值
newsParms[0].Value = title;
//一个获取文件名的私有方法
newsParms[1].Value = getFilename().ToString();
xmlfilename = getFilename().ToString();
//注意发布的日期取当日
newsParms[2].Value = DateTime.Now;
//默认添加的回复数是0
newsParms[3].Value = 0;
newsParms[4].Value = DateTime.Now;
newsParms[5].Value = user;
newsParms[6].Value = categoryid;
//遍历所有参数,并将参数添加到SqlCommand命令中
foreach (SqlParameter parm in newsParms)
cmd.Parameters.Add(parm);
//获取数据库的连接字符串
using (SqlConnection conn = new SqlConnection(SqlHelper.ConnectionStringLocalTransaction))
{
strSQL.Append(SQL_INSERT_BBSINFO);
//打开数据库连接,执行命令
conn.Open();
//设置Sqlcommand命令的属性
cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
cmd.CommandText = strSQL.ToString();
//执行添加的SqlCommand命令
int val = cmd.ExecuteNonQuery();
//清空SqlCommand命令中的参数
cmd.Parameters.Clear();
}
}
/// <summary>
/// 创建或获取缓存参数的私有方法
/// </summary>
/// <returns>返回参数列表</returns>
private static SqlParameter[] GetParameters()
{
//将SQL_INSERT_NEWSINFO做为哈希表缓存的键值
SqlParameter[] parms = SqlHelper.GetCachedParameters(SQL_INSERT_BBSINFO);
//首先判断缓存是否已经存在
if (parms == null)
{
//缓存不存在的情况下,新建参数列表
parms = new SqlParameter[] {
new SqlParameter(PARM_BBS_TITLE, SqlDbType.NVarChar,50),
new SqlParameter(PARM_BBS_FILENAME, SqlDbType.NVarChar,100),
new SqlParameter(PARM_BBS_POSTTIME, SqlDbType.DateTime),
new SqlParameter(PARM_BBS_REPLYCOUNT, SqlDbType.Int),
new SqlParameter(PARM_BBS_LASTREPLYTIME, SqlDbType.DateTime),
new SqlParameter(PARM_BBS_POSTUSER, SqlDbType.NVarChar, 50),
new SqlParameter(PARM_BBS_CATEGORYID, SqlDbType.Int) };
//将新建的参数列表添加到哈希表中缓存起来
SqlHelper.CacheParameters(SQL_INSERT_BBSINFO, parms);
}
//返回参数数组
return parms;
}
/// <summary>
/// 更新数据库中的回复时间
/// </summary>
/// <param name="infoid">帖子的ID</param>
/// <returns>是否更新成功</returns>
public bool UpdateMsg(int infoid)
{
//使用StringBuild连接字符串比使用“+”效率高很多
StringBuilder strSQL = new StringBuilder();
//创建论坛添加方法的参数
SqlParameter[] newsParms = new SqlParameter[]{
new SqlParameter("@lastposttime", SqlDbType.DateTime),
new SqlParameter("@infoid", SqlDbType.Int)};
//创建执行语句的SQL命令
SqlCommand cmd = new SqlCommand();
// 依次给参数赋值
newsParms[0].Value = DateTime.Now;
newsParms[1].Value = infoid;
//遍历所有参数,并将参数添加到SqlCommand命令中
foreach (SqlParameter parm in newsParms)
cmd.Parameters.Add(parm);
//获取数据库的连接字符串
using (SqlConnection conn = new SqlConnection(SqlHelper.ConnectionStringLocalTransaction))
{
//加载“添加类别”执行语句
strSQL.Append("UPDATE bbsinfo SET replycount=replycount+1 , lastreplytime=@lastposttime WHERE infoid=@infoid");
//打开数据库连接,执行命令
conn.Open();
//设置Sqlcommand命令的属性
cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
cmd.CommandText = strSQL.ToString();
//执行添加的SqlCommand命令
int val = cmd.ExecuteNonQuery();
//清空SqlCommand命令中的参数
cmd.Parameters.Clear();
//判断是否添加成功,注意返回的是添加是否成功,不是影响的行数
if (val > 0)
return true;
else
return false;
}
}
/// <summary>
/// 给新建的xml文件起名
/// </summary>
/// <returns>返回的是最大号的ID+1</returns>
private int getFilename()
{
int cardrule = 0;
//设置SQL语句,取最大的ID值
string strsql = "select top 1 infoid from bbsinfo order by infoid desc ";
//调用SqlHelper访问组件的方法返回第一行第一列的值
try
{
cardrule = (int)SqlHelper.ExecuteScalar(SqlHelper.ConnectionStringLocalTransaction, CommandType.Text, strsql, null);
//返回最大值+1
}
catch
{
//此时数据库中无数据
cardrule = 0;
}
return cardrule +1;
}
/// <summary>
/// 更新回复内容
/// </summary>
/// <param name="filename">文件名</param>
/// <param name="title">回复主题</param>
/// <param name="content">回复内容</param>
/// <param name="user">回复人</param>
public void UpdateXml(string filename,string title,string content,string user)
{
//初始化XML文档操作类
XmlDocument mydoc = new XmlDocument();
//加载指定的XML文件
mydoc.Load(filename);
//添加元素-帖子主题
XmlElement ele = mydoc.CreateElement("title");
XmlText text = mydoc.CreateTextNode(title);
//添加元素-发帖时间
XmlElement ele1 = mydoc.CreateElement("posttime");
XmlText text1 = mydoc.CreateTextNode(DateTime.Now.ToString());
//添加元素-内容
XmlElement ele2 = mydoc.CreateElement("content");
XmlText text2 = mydoc.CreateTextNode(content);
//添加元素-发帖人
XmlElement ele3 = mydoc.CreateElement("postuser");
XmlText text3 = mydoc.CreateTextNode(user);
//添加文件的节点-msgrecord
XmlNode newElem = mydoc.CreateNode("element", "xmlrecord", "");
//在节点中添加元素
newElem.AppendChild(ele);
newElem.LastChild.AppendChild(text);
newElem.AppendChild(ele1);
newElem.LastChild.AppendChild(text1);
newElem.AppendChild(ele2);
newElem.LastChild.AppendChild(text2);
newElem.AppendChild(ele3);
newElem.LastChild.AppendChild(text3);
//将节点添加到文档中
XmlElement root = mydoc.DocumentElement;
root.AppendChild(newElem);
//保存所有的修改
mydoc.Save(filename);
}
}