昨天有朋友说,使用PageAdapter要比BasePage好,使用PageAdapter便于统一管理和配置,这次我用PageAdapter实现同样的效果,同时也对原来的代码也做了一些修改,使之性能有所提升。
读取控件状态,不是直接从数据库读取,而是先去状态池中查找,如果状态池中不存在,我们再访问数据库。
保存的过程和读取的过程相对应,控件状态先保存至状态池,当状态池满时,将其中的部分元素保存只数据库。
状态池中的元素都是未序列化的,这样就避免了序列化和反序列化带来的性能问题。

Code
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;

namespace JianCaiWeb.Utils
{
    /**//// <summary>
    /// 读取控件状态,不是直接从数据库读取,而是先去状态池中查找,如果状态池中不存在,我们再访问数据库。
    /// 
    /// 状态池中的元素都是未序列化的,这样就避免了序列化和反序列化带来的性能问题。
    /// </summary>
    public class DatabasePageStatePersister : PageStatePersister
    {
        private static DataAccess da;
        //状态池
        private static List<DictionaryEntry> list = new List<DictionaryEntry>();

        public DatabasePageStatePersister(Page page)
            : base(page)
        {
            da = DataAccessFactory.CreateDataAccess();
        }

        //在 Page 对象初始化其控件层次结构时,加载保留的状态信息
        public override void Load()
        {
            string stateID = base.Page.Request["__VIEWSTATE_KEY"].ToString();
            Pair 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);

                this.SaveViewState(viewStateID, statePair);
            }
        }
        //保存视图状态至状态池或数据库
        private void SaveViewState(string viewStateID, Pair statePair)
        {
            DictionaryEntry newEntry = new DictionaryEntry();
            newEntry.Key = viewStateID;
            newEntry.Value = statePair;
            list.Add(newEntry);

            //当al中的元素数量大于等于1000时,将其前10条放入数据库
            if (list.Count >= 1000)
            {
                //声明一数组,用于存放al的前10条元素
                DictionaryEntry[] entryArray = new DictionaryEntry[10];
                //al的前10条元素拷贝至objs数组中
                list.CopyTo(0, entryArray, 0, 10);
                //从al中移除前10条元素
                list.RemoveRange(0, 10);

                //循环遍历objs,将其所包含的元素存入数据库中
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < 10; i++)
                {
                    DictionaryEntry oldEntry = entryArray[i];
                    //获取页面的StateFormmatter
                    IStateFormatter formatter = this.StateFormatter;
                    //序列化控件状态
                    string serializedState = formatter.Serialize(oldEntry.Value);

                    sb.Append(string.Format("insert into ViewState (viewStateID,ViewState) values ('{0}','{1}');", oldEntry.Key, serializedState));
                }
                //将控件状态存入数据库
                da.ExecuteNonQuery(sb.ToString());
            }
        }
        //从状态池或数据库中读取控件状态
        private Pair LoadViewState(string viewStateID)
        {
            Pair statePair = null;
            //遍历状态池,找到相应的控件状态
            foreach (DictionaryEntry entry in list)
            {
                if (entry.Key.ToString() == viewStateID)
                {
                    statePair = (Pair)entry.Value;
                    //list.Remove(entry);
                    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;
        }
    }
}

下边是继承PageAdapter的类,当页面的EnableViewState为true时,调用我们自定义的类(DataBasePageStatePersister),否则调用基类的实现。

Code
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;

namespace JianCaiWeb.Utils
{
    public class DataBasePageAdapter : System.Web.UI.Adapters.PageAdapter
    {

        public override PageStatePersister GetStatePersister()
        {
            if (Page.EnableViewState == true)
                return new DatabasePageStatePersister(Page);
            else
                return base.GetStatePersister();
        }
    }
}

我们还需要在应用程序浏览器目录App_Browsers,然后在其中建立浏览器文件,文件的内容如下:

<!--
可在 <windir>\Microsoft.NET\Framework\<ver>\CONFIG\Browsers 中找到现有的浏览器定义
-->
<browsers>
  <browser refID="Default" >
    <controlAdapters>
      <adapter
          controlType="System.Web.UI.Page"
          adapterType="JianCaiWeb.Utils.DataBasePageAdapter" />
    </controlAdapters>
  </browser>
</browsers>

转载于:https://www.cnblogs.com/fengfeng/archive/2008/05/05/1183274.html

将视图状态存入数据库(3)相关推荐

  1. java 捕获异常并存入数据库_java异常处理,报异常的话怎么处理对象值,并持久化到数据库中...

    展开全部 //没看到有人回e68a843231313335323631343130323136353331333365646233答你,我还没学到框架,不知道那个是不是可以很便捷操作你说的这样过程 / ...

  2. JS同时上传表单图片和表单信息并把上传信息存入数据库,带php后端源码

    微信小程序开发交流qq群   581478349    承接微信小程序开发.扫码加微信. 利用JQ,jquery.form.js,bootstrap实现上传表单图片和表单信息并把上传的图片地址,inp ...

  3. 微信小程序获取openid和session_key并且把openid存入数据库

    微信小程序开发交流qq群   581478349 微信小程序获取openid和session_key并且把openid存入数据库.已经调用openid的demo 前后端代码都有,后端php实现 在其它 ...

  4. 用Scrapy爬虫框架爬取食品论坛数据并存入数据库

    这篇文章主要给大家介绍了食品网站的数据采集和存储过程,详解了如何分析网页结构.爬虫策略.网站类型.层级关系.爬虫方法和数据存储过程,最终实现将帖子的每条评论爬取到数据库中,并且做到可以更新数据,防止重 ...

  5. java 打开服务器excel文件_Java中上传excel文件并在服务器端读取存入数据库

    传excel文件并在服务器端读取存入数据库 博客分类: struts2 Excel JSP XML 工作 Java代码 页面jsp文件 action处理:publicclassManyContacts ...

  6. php 变量写入数据库,PHP基础/JS变量存入数据库 | 学步园

    今天在研究腾讯的第三方接入 ,参照 遇到的一个必经的问题是,如何把js变量存入数据库中. 1 . 实际需求是把  openId 以及 accessToken 存入mysql中 ,以便维护用户的信息. ...

  7. JDBC进阶:调用数据库,将文件或其他字节文件存入数据库,再从数据库取出写回硬盘

    package star.july.practise; /*** JDBC进阶:调用数据库,将文件或其他字节文件存入数据库,* 再从数据库取出写回硬盘*/ import java.io.File; i ...

  8. php 数组存入mysql_PHP将数组存入数据库中的四种方式

    1.implode()和explode()方式 2.print_r()和自定义函数方式 3.serialize()和unserialize()方式 4.json_encode()和json_decod ...

  9. PHP将数组存入数据库中的四种方式

    最近突然遇到了一个问题,如何用PHP将数组存入到数据库中,经过自己的多方查找和研究,总结了以下四种方法: 1.implode()和explode()方式 2.print_r()和自定义函数方式 3.s ...

最新文章

  1. Jürgen Schmidhuber回顾30年前旧作,称其启发了现今流行的很多概念
  2. JSON与JAVA数据的转换
  3. 第一章 深入.NET框架
  4. jsp判断字符串相等_最长回文字符串三种解法
  5. GetOpenFileName的简单使用实例
  6. C#自定义ConfigSections节点操作
  7. 机器字长、存储字长、指令字长
  8. 绿色iPhone 13和紫色iPad Air将在明天发布?网友:苹果又寻思在配色上“整活儿”...
  9. SharingSphere 源码解析 -- 真实SQL生成探索
  10. Use a production WSGI server instead(搭建web网站出现的问题)
  11. 用sitemesh来装饰动态的左侧菜单和内容部分
  12. android ndk串口触屏,Aandroid NDK开发之串口控制
  13. 51单片机循迹小车c语言程序,51单片机循迹小车源程序
  14. 项目管理计划包含哪些内容
  15. 白化滤波器 matlab,白化滤波器-matlab-程序.doc
  16. 三星 android 调试模式设置,三星galaxy s4 usb调试在哪里 s4 usb调试模式设置方法详解...
  17. 遗传算法java(中国外运杯)
  18. 中文姓名按照拼音排序-python
  19. 关于IDEA不生成out文件无法执行程序的问题
  20. cocos2dx+VS2019环境配置

热门文章

  1. LeetCode(1021)——删除最外层的括号(JavaScript)
  2. git commit -m 'comment' 遇到 'npm' 不是内部或外部命令,也不是可运行的程序 或批处理文件。
  3. sofa-pbrpc框架的简单使用
  4. 【零基础学Java】—final关键字与四种用法(二十九)
  5. asp向不同的用户发送信息_.Net Core 和 .Net Framework的不同
  6. 决定要放下的人,要不要好好道个别?
  7. 成年人的生活到底有多心酸?
  8. 很多朋友问做自媒体的意义是什么?
  9. 生意做到一定规模,老板想面面俱到,亲力亲为就不可能了
  10. vector常见用法