将视图状态存入数据库(1)
在使用.Net开发程序的时候,一般来讲,免不了要使用视图状态,默认情况下,视图状态在页面上,如果我们手动修改某些方法,视图状态也可以保存在数据库中、文本中或Session中,今天我们说说如果将视图状态保存至数据库中,网上有不少类似的文章,在这里,我想说一点不同的地方。首先我把代码给贴出来
using System;
using System.Web.UI;
using System.IO;
using ICSharpCode.SharpZipLib.Zip.Compression;
using System.Collections;
using JianCaiWeb.DbAccess;
using System.Text;
namespace JianCaiWeb.Utils
{
/**/
/// <summary>
/// PageClass 的摘要说明。
/// </summary>
public class BasePage : System.Web.UI.Page
{
protected override PageStatePersister PageStatePersister
{
get
{
return new DatabasePageStatePersister(this);
}
}
}
public class DatabasePageStatePersister : PageStatePersister
{
private static DataAccess da;
private static Hashtable ht = new Hashtable(50);
public DatabasePageStatePersister(Page page)
: base(page)
{
da = DataAccessFactory.CreateDataAccess();
}
//载入控件状态
public override void Load()
{
string stateID = base.Page.Request["__VIEWSTATE_KEY"].ToString();
string viewState = this.LoadViewState(stateID);
IStateFormatter formatter = this.StateFormatter;
Pair statePair = (Pair)formatter.Deserialize(viewState);
this.ViewState = statePair.First;
this.ControlState = statePair.Second;
}
// 保存控件状态
public override void Save()
{
if (this.ViewState != null || this.ControlState != null)
{
Random random = new Random();
string viewStateID = "VIEWSTATE_" + random.Next(0, 10000) + DateTime.Now.ToString("yyyyMMddhhmmss");
base.Page.ClientScript.RegisterHiddenField("__VIEWSTATE_KEY", viewStateID);
Pair statePair = new Pair(ViewState, ControlState);
IStateFormatter formatter = this.StateFormatter;
string serializedState = formatter.Serialize(statePair);
this.SaveViewState(viewStateID, serializedState);
}
}
//保存ViewState
private void SaveViewState(string viewStateID,string viewState)
{
//当Hashtable中的记录达到50时,提交至数据库,同时清空Hashtable集合
if (ht.Count == 50)
{
lock (ht.SyncRoot)
{
StringBuilder sb = new StringBuilder();
foreach (DictionaryEntry entry in ht)
{
sb.Append(string.Format("insert into ViewState (viewStateID,ViewState) values ('{0}','{1}');", entry.Key, entry.Value));
}
int ret = da.ExecuteNonQuery(sb.ToString());
if (ret == 0)
throw new Exception("更新ViewState失败,请与管理员联系");
}
ht.Clear();
}
else //将ViewState的Key和Value放入Hashtable中
ht.Add(viewStateID, viewState);
}
//读取ViewState
private string LoadViewState(string viewStateID)
{
string viewState = ht[viewStateID].ToString();
if (viewState == null)
{
string strSql = "select viewState from viewState where viewStateID = '" + viewStateID + "'";
viewState = da.ExecuteScalar(strSql).ToString();
}
return viewState;
}
}
}
仔细看代码的朋友应该很容易发现,我们并不是每次访问或存储视图状态都要访问数据库,而是将视图状态的最新的一部分视图状态保存一个静态的Hashtable中,当Hashtable中的记录达到一定的数量时,我们批量更新至数据库,同时清空Hashtable。读取的时候,先检查一下,看看Hashtable中是否已存在,如果不存在我们再访问数据库,这样做,我们就能有效的减少访问数据库的次数。同时也在一定程度上提高读取视图状态的性能。 using System.Web.UI;
using System.IO;
using ICSharpCode.SharpZipLib.Zip.Compression;
using System.Collections;
using JianCaiWeb.DbAccess;
using System.Text;
namespace JianCaiWeb.Utils
{
/**/
/// <summary>
/// PageClass 的摘要说明。
/// </summary>
public class BasePage : System.Web.UI.Page
{
protected override PageStatePersister PageStatePersister
{
get
{
return new DatabasePageStatePersister(this);
}
}
}
public class DatabasePageStatePersister : PageStatePersister
{
private static DataAccess da;
private static Hashtable ht = new Hashtable(50);
public DatabasePageStatePersister(Page page)
: base(page)
{
da = DataAccessFactory.CreateDataAccess();
}
//载入控件状态
public override void Load()
{
string stateID = base.Page.Request["__VIEWSTATE_KEY"].ToString();
string viewState = this.LoadViewState(stateID);
IStateFormatter formatter = this.StateFormatter;
Pair statePair = (Pair)formatter.Deserialize(viewState);
this.ViewState = statePair.First;
this.ControlState = statePair.Second;
}
// 保存控件状态
public override void Save()
{
if (this.ViewState != null || this.ControlState != null)
{
Random random = new Random();
string viewStateID = "VIEWSTATE_" + random.Next(0, 10000) + DateTime.Now.ToString("yyyyMMddhhmmss");
base.Page.ClientScript.RegisterHiddenField("__VIEWSTATE_KEY", viewStateID);
Pair statePair = new Pair(ViewState, ControlState);
IStateFormatter formatter = this.StateFormatter;
string serializedState = formatter.Serialize(statePair);
this.SaveViewState(viewStateID, serializedState);
}
}
//保存ViewState
private void SaveViewState(string viewStateID,string viewState)
{
//当Hashtable中的记录达到50时,提交至数据库,同时清空Hashtable集合
if (ht.Count == 50)
{
lock (ht.SyncRoot)
{
StringBuilder sb = new StringBuilder();
foreach (DictionaryEntry entry in ht)
{
sb.Append(string.Format("insert into ViewState (viewStateID,ViewState) values ('{0}','{1}');", entry.Key, entry.Value));
}
int ret = da.ExecuteNonQuery(sb.ToString());
if (ret == 0)
throw new Exception("更新ViewState失败,请与管理员联系");
}
ht.Clear();
}
else //将ViewState的Key和Value放入Hashtable中
ht.Add(viewStateID, viewState);
}
//读取ViewState
private string LoadViewState(string viewStateID)
{
string viewState = ht[viewStateID].ToString();
if (viewState == null)
{
string strSql = "select viewState from viewState where viewStateID = '" + viewStateID + "'";
viewState = da.ExecuteScalar(strSql).ToString();
}
return viewState;
}
}
}
有几点说明一下:
DataAccess是一个数据库访问类,我没有提供相应的代码,你可以替换成你自己的。
使用的时候,你只需用BasePage替换掉页面的System.Web.UI.Page即可。