将视图状态存入数据库(4)
前几天写了篇将视图状态存入数据库(3),这次发布的文件,修正了当控件状态比较小时,不保存在数据库中,而是保存在页面上。
using System;
using System.Web.UI;
using System.IO;
using ICSharpCode.SharpZipLib.Zip.Compression;
using System.Collections;
using JianCaiWeb.DbAccess;
using System.Text;
using System.Collections.Generic;
using System.Reflection;
namespace JianCaiWeb.Utils
{
/// <summary>
/// 读取控件状态,不是直接从数据库读取,而是先去状态池中查找,如果状态池中不存在,我们再访问数据库。
///
/// 状态池中的元素都是未序列化的,这样就避免了序列化和反序列化带来的性能问题。
/// </summary>
public class DatabasePageStatePersister : PageStatePersister
{
private static DataAccess da;
private static int limitLength = 548;
//状态池
private static List<DictionaryEntry> list = new List<DictionaryEntry>();
//状态池大小
private static int viewStateCount = 1000;
public DatabasePageStatePersister(Page page)
: base(page)
{
da = DataAccessFactory.CreateDataAccess();
}
//在 Page 对象初始化其控件层次结构时,加载保留的状态信息
public override void Load()
{
Pair statePair = null;
string clicentState = this.Page.Request["__VIEWSTATE"].ToString();
if (clicentState.Length != 0)
{
//获取页面的StateFormmatter
IStateFormatter formatter = this.StateFormatter;
//序列化控件状态
statePair = (Pair)formatter.Deserialize(clicentState);
}
else
{
string stateID = base.Page.Request["__VIEWSTATE_KEY"].ToString();
statePair = this.LoadViewState(stateID);
}
this.ViewState = statePair.First;
this.ControlState = statePair.Second;
}
// 在从内存中卸载 Page 对象时,对所保留的状态信息进行序列化。
public override void Save()
{
if (this.ViewState != null || this.ControlState != null)
{
Guid guid = Guid.NewGuid();
string viewStateID = guid.ToString();
base.Page.ClientScript.RegisterHiddenField("__VIEWSTATE_KEY", viewStateID);
Pair statePair = new Pair(ViewState, ControlState);
//获取页面的StateFormmatter
IStateFormatter formatter = this.StateFormatter;
//序列化控件状态
string serializedState = formatter.Serialize(statePair);
if (serializedState.Length < limitLength)
{
//通过反射,找到页面实例的ClientState属性,将控件状态赋值给改属性
Type type = this.Page.GetType();
PropertyInfo property = type.GetProperty("ClientState", BindingFlags.Instance | BindingFlags.NonPublic);
property.SetValue(this.Page, serializedState, null);
}
else
this.SaveViewState(viewStateID, statePair, serializedState);
}
}
//保存视图状态至状态池或数据库
private void SaveViewState(string viewStateID, Pair statePair, string serializedState)
{
DictionaryEntry newEntry = new DictionaryEntry();
newEntry.Key = viewStateID;
newEntry.Value = statePair;
list.Add(newEntry);
string strSql = string.Format("insert into ViewState (viewStateID,ViewState) values ('{0}','{1}');", viewStateID, serializedState);
//将控件状态存入数据库
da.ExecuteNonQuery(strSql);
//当状态池中的元素数量大于等于1000时,从开始位置移除多余的元素
if (list.Count >= viewStateCount)
{
list.RemoveRange(0, list.Count - viewStateCount);
}
}
//从状态池或数据库中读取控件状态
private Pair LoadViewState(string viewStateID)
{
Pair statePair = null;
//遍历状态池,找到相应的控件状态
foreach (DictionaryEntry entry in list)
{
if (entry.Key.ToString() == viewStateID)
{
statePair = (Pair)entry.Value;
break;
}
}
//如果状态池中没有找到相应的控件状态,则从数据库中读取
if (statePair == null)
{
string strSql = "select viewState from viewState where viewStateID = '" + viewStateID + "'";
string viewState = da.ExecuteScalar(strSql).ToString();
//获取页面的StateFormmatter
IStateFormatter formatter = this.StateFormatter;
//序列化控件状态
statePair = (Pair)formatter.Deserialize(viewState);
}
return statePair;
}
}
}
具体怎么使用,参考将视图状态存入数据库(3)。
using System.Web.UI;
using System.IO;
using ICSharpCode.SharpZipLib.Zip.Compression;
using System.Collections;
using JianCaiWeb.DbAccess;
using System.Text;
using System.Collections.Generic;
using System.Reflection;
namespace JianCaiWeb.Utils
{
/// <summary>
/// 读取控件状态,不是直接从数据库读取,而是先去状态池中查找,如果状态池中不存在,我们再访问数据库。
///
/// 状态池中的元素都是未序列化的,这样就避免了序列化和反序列化带来的性能问题。
/// </summary>
public class DatabasePageStatePersister : PageStatePersister
{
private static DataAccess da;
private static int limitLength = 548;
//状态池
private static List<DictionaryEntry> list = new List<DictionaryEntry>();
//状态池大小
private static int viewStateCount = 1000;
public DatabasePageStatePersister(Page page)
: base(page)
{
da = DataAccessFactory.CreateDataAccess();
}
//在 Page 对象初始化其控件层次结构时,加载保留的状态信息
public override void Load()
{
Pair statePair = null;
string clicentState = this.Page.Request["__VIEWSTATE"].ToString();
if (clicentState.Length != 0)
{
//获取页面的StateFormmatter
IStateFormatter formatter = this.StateFormatter;
//序列化控件状态
statePair = (Pair)formatter.Deserialize(clicentState);
}
else
{
string stateID = base.Page.Request["__VIEWSTATE_KEY"].ToString();
statePair = this.LoadViewState(stateID);
}
this.ViewState = statePair.First;
this.ControlState = statePair.Second;
}
// 在从内存中卸载 Page 对象时,对所保留的状态信息进行序列化。
public override void Save()
{
if (this.ViewState != null || this.ControlState != null)
{
Guid guid = Guid.NewGuid();
string viewStateID = guid.ToString();
base.Page.ClientScript.RegisterHiddenField("__VIEWSTATE_KEY", viewStateID);
Pair statePair = new Pair(ViewState, ControlState);
//获取页面的StateFormmatter
IStateFormatter formatter = this.StateFormatter;
//序列化控件状态
string serializedState = formatter.Serialize(statePair);
if (serializedState.Length < limitLength)
{
//通过反射,找到页面实例的ClientState属性,将控件状态赋值给改属性
Type type = this.Page.GetType();
PropertyInfo property = type.GetProperty("ClientState", BindingFlags.Instance | BindingFlags.NonPublic);
property.SetValue(this.Page, serializedState, null);
}
else
this.SaveViewState(viewStateID, statePair, serializedState);
}
}
//保存视图状态至状态池或数据库
private void SaveViewState(string viewStateID, Pair statePair, string serializedState)
{
DictionaryEntry newEntry = new DictionaryEntry();
newEntry.Key = viewStateID;
newEntry.Value = statePair;
list.Add(newEntry);
string strSql = string.Format("insert into ViewState (viewStateID,ViewState) values ('{0}','{1}');", viewStateID, serializedState);
//将控件状态存入数据库
da.ExecuteNonQuery(strSql);
//当状态池中的元素数量大于等于1000时,从开始位置移除多余的元素
if (list.Count >= viewStateCount)
{
list.RemoveRange(0, list.Count - viewStateCount);
}
}
//从状态池或数据库中读取控件状态
private Pair LoadViewState(string viewStateID)
{
Pair statePair = null;
//遍历状态池,找到相应的控件状态
foreach (DictionaryEntry entry in list)
{
if (entry.Key.ToString() == viewStateID)
{
statePair = (Pair)entry.Value;
break;
}
}
//如果状态池中没有找到相应的控件状态,则从数据库中读取
if (statePair == null)
{
string strSql = "select viewState from viewState where viewStateID = '" + viewStateID + "'";
string viewState = da.ExecuteScalar(strSql).ToString();
//获取页面的StateFormmatter
IStateFormatter formatter = this.StateFormatter;
//序列化控件状态
statePair = (Pair)formatter.Deserialize(viewState);
}
return statePair;
}
}
}