将视图状态存入数据库(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(010000+ 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中是否已存在,如果不存在我们再访问数据库,这样做,我们就能有效的减少访问数据库的次数。同时也在一定程度上提高读取视图状态的性能。
有几点说明一下:
DataAccess是一个数据库访问类,我没有提供相应的代码,你可以替换成你自己的。
使用的时候,你只需用BasePage替换掉页面的System.Web.UI.Page即可。
posted @ 2008-04-29 15:20  王庆  阅读(713)  评论(0编辑  收藏  举报