You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何防止Web窗体DataTable被不同计算机用户跨会话访问

问题根因

和DataTable本身无关,核心问题是你错误使用了static静态变量存储用户私有状态,直接导致跨用户数据串扰。
ASP.NET 中类的静态变量是应用程序域级别的全局共享资源,所有访问当前站点的用户,都会读写同一个静态变量实例。你在页面类中做了如下声明:

public partial class Tvrtb : System.Web.UI.Page
{
    // 用于为日历控件着色的ArrayList
    static ArrayList datesArray;
    static DataTable dtArray;
}

这种写法下,不管多少用户、从什么终端登录,所有操作都会修改同一份datesArray和dtArray:A选的日期会写到共享实例里,B访问时读到的就是A写进去的数据,反过来B的修改也会被A看到,就是你遇到的串扰现象。
除此之外你的代码还有两个明显的状态管理bug:

  • 只在首次非回发请求(!IsPostBack)中初始化了dtArray,datesArray从未做初始化,首次点击日期时存在空引用异常风险;
  • 虽然在gvbind方法里把两个对象存入了ViewState,但从未在页面生命周期早期从ViewState读回值,完全依赖静态变量的共享值维持状态,不仅串用户,一旦应用池回收释放静态变量,用户的操作状态会直接丢失。
修复方案

不需要放弃DataTable,只要修正变量作用域和状态读写逻辑即可,具体修改步骤:

  • 移除两个字段的static修饰符,改为页面类的普通实例字段,每个请求的页面实例会独立持有这两个对象,不会共享:
    public partial class Tvrtb : System.Web.UI.Page
    {
        ArrayList datesArray;
        DataTable dtArray;
    }
    
  • 补全Page_Load中的状态恢复逻辑,每次页面加载时先从ViewState读回之前存储的用户操作数据,仅在首次访问时初始化新的对象:
    protected void Page_Load(object sender, EventArgs e)
    {
        // 回发时从ViewState恢复用户之前选的数据
        if (ViewState["selectedDates"] != null)
        {
            datesArray = (ArrayList)ViewState["selectedDates"];
        }
        if (ViewState["vsDTArray"] != null)
        {
            dtArray = (DataTable)ViewState["vsDTArray"];
        }
    
        if (!Page.IsPostBack)
        {
            // 首次访问初始化空数据结构
            datesArray = new ArrayList();
            dtArray = new DataTable();
            dtArray.Columns.Add("VacReqNum", typeof(string));
            dtArray.Columns.Add("ReqDate", typeof(DateTime));
            dtArray.Columns.Add("ReqHours", typeof(string));
            dtArray.Columns.Add("VacReqID", typeof(string));
            dtArray.Columns.Add("VacReqDayID", typeof(string));
            
            // 初始化后存入ViewState,供后续回发使用
            ViewState["selectedDates"] = datesArray;
            ViewState["vsDTArray"] = dtArray;
    
            // 首次加载的控件状态初始化
            cleb.Visible = true;
            NewVac.Visible = false;
        }
    }
    
  • 原有日期选择、GridView绑定的业务逻辑不需要大改,DisplaySelectedDates方法直接读取当前实例的datesArray给日历着色即可,每个用户的状态存在自己页面的ViewState中,完全隔离,不会再出现串扰。
可选替代实现方案

如果觉得ViewState存储DataTable会增加页面渲染体积(ViewState会序列化后存在页面隐藏域,随请求回传),可以选择以下方案:

  • 用Session存储用户临时选的日期数据:逻辑和上述ViewState写法完全一致,只是把读写载体换成Session,数据存在服务端,不会增加页面传输体积,注意Session有默认过期时间,适合这类短时间填表的场景。
  • 前端维护临时状态:用JS在前端记录用户选中的日期、填写的休假时长,不需要每次选日期都回发服务端,等用户最终提交申请时,一次性把所有数据传到服务端做校验入库,这种方案服务端不需要在填表过程中维护临时状态,性能最优,也从根源上避免了状态共享导致的串扰问题。

注意:静态变量仅适合存储全应用共享的全局数据,比如系统配置、公共缓存类内容,绝对不要用来存储单个用户的私有临时状态,只要用静态变量存用户数据,必然会出现跨用户串扰问题。

内容的提问来源于stack exchange,提问作者Huerita37

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 18:48:54