项目 LZJYXT 感触 ---- 用 Session 进行跨页面参数传递

注: 该实例代码只是为了说明问题, 实则不建议直接用 Session 来记录数据

Session: 在计算机中,尤其是在网络应用中,称为“会话”。

背景: 在 Grade 页面里面会对某一年级的数据进行处理, 同时在该页面可以连接到 Class 页面对该年级的某一个班级的数据进行处理, 所以把 Grade 的年级数据集存在 Session 里面, 然后在跳转 _Class 页面时, 需要的数据集就可以直接对 Session 里面的数据进行筛选然后取用, 不用再去搜索一次数据库;

初次实现:

TestData
 1 ///<summary>
2 /// 数据类
3 ///</summary>
4 public class TestData
5 {
6 ///<summary>
7 /// 学生 ID
8 ///</summary>
9 public string StudentID { get; set; }
10
11 ///<summary>
12 /// 入学年份
13 ///</summary>
14 public int SchoolYear { get; set; }
15
16 ///<summary>
17 /// 班级
18 ///</summary>
19 public int Class { get; set; }
20
21 ///<summary>
22 /// 学生分数
23 ///</summary>
24 public float Score { get; set; }
25
26 ///<summary>
27 /// 创建一个数据集
28 ///</summary>
29 ///<returns></returns>
30 public static List<TestData> GetDataList()
31 {
32 List<TestData> dataList = new List<TestData>();
33
34 for (int i = 0; i < 30; i++)
35 {
36 // 创建一个 TestData 并为它的各个属性赋值
37 TestData data = new TestData
38 {
39 SchoolYear = 2008 + i / 10,
40 Class = i / 5 + 1,
41 Score = 100,
42 };
43 data.StudentID = string.Format("{0}{1}{2}", data.SchoolYear, data.Class.ToString("D2"), i.ToString("D3"));
44
45 dataList.Add(data);
46 }
47
48 return dataList;
49 }
50
51 ///<summary>
52 /// 将一个 TestDataList 以 string 的形式返回
53 ///</summary>
54 ///<param name="dataList"></param>
55 ///<returns></returns>
56 public static string ShowDataList(List<TestData> dataList)
57 {
58 System.Text.StringBuilder sb = new System.Text.StringBuilder();
59 foreach (var d in dataList)
60 {
61 sb.AppendFormat("ID: {0}, Year: {1}, Class: {2}, Score: {3}<br/>", d.StudentID, d.SchoolYear, d.Class, d.Score);
62 }
63 return sb.ToString();
64 }
65 }
Grade.aspx
1         <asp:Literal ID="ltlTestData" runat="server"></asp:Literal><br />
2 <asp:Button ID="btnShowData" runat="server" Text="显示数据"
3 onclick="btnShowData_Click"/><br />
4 <asp:Literal ID="ltlGardes" runat="server"></asp:Literal><br />
5 <asp:Literal ID="ltlClasses" runat="server"></asp:Literal>
Grade.aspx.cs
 1     protected void Page_Load(object sender, EventArgs e)
2 {
3 // 初始化 dataList
4 List<TestData> dataList = (List<TestData>)Session["TestData"];
5 if (dataList == null)
6 {
7 dataList = TestData.GetDataList();
8 Session["TestData"] = dataList;
9 }
10
11 // 获取年级参数
12 string year = Request.QueryString["y"];
13 if (year != null)
14 {
15 int schoolYear = Convert.ToInt32(year);
16 dataList = dataList.FindAll(p => p.SchoolYear == schoolYear); // 年级数据筛选
17 Session["TestData"] = dataList;
18 BindltlClasses(); // 创建班级链接
19 ltlClasses.Visible = true;
20 ltlGardes.Visible = false;
21 }
22 else
23 {
24 BindltlGrades(); // 创建年级链接
25 ltlGardes.Visible = true;
26 ltlClasses.Visible = false;
27 }
28 }
29
30 ///<summary>
31 /// 创建年级链接
32 ///</summary>
33 ///<param name="dataList"></param>
34 private void BindltlGrades()
35 {
36 List<TestData> dataList = (List<TestData>)Session["TestData"];
37
38 var grades = from td in dataList
39 select td.SchoolYear;
40 grades = grades.Distinct();
41
42 System.Text.StringBuilder sb = new System.Text.StringBuilder();
43 foreach (var g in grades)
44 {
45 sb.AppendFormat("<a href=\"Grade.aspx?y={0}\">{0}</a><br/>", g);
46 }
47 ltlGardes.Text = sb.ToString();
48 ltlGardes.Visible = true;
49 }
50
51 ///<summary>
52 /// 创建班级链接
53 ///</summary>
54 private void BindltlClasses()
55 {
56 List<TestData> dataList = (List<TestData>)Session["TestData"];
57
58 var classes = from td in dataList
59 select td.Class;
60 classes = classes.Distinct();
61
62 System.Text.StringBuilder sb = new System.Text.StringBuilder();
63 foreach (var c in classes)
64 {
65 sb.AppendFormat("<a href=\"_Class.aspx?c={0}\">{0}</a><br/>", c);
66 }
67 ltlClasses.Text = sb.ToString();
68 }
69
70 protected void btnShowData_Click(object sender, EventArgs e)
71 {
72 ltlTestData.Text = TestData.ShowDataList((List<TestData>)Session["TestData"]);
73 }
_Class.aspx
1         <asp:Literal ID="ltlTestData" runat="server"></asp:Literal><br />
2 <asp:Button ID="btnShowData" runat="server" Text="显示数据"
3 onclick="btnShowData_Click"/><br />
4 <a href="Grade.aspx">Grade</a>
_Class.aspx.cs
 1     protected void Page_Load(object sender, EventArgs e)
2 {
3 // 获取班级
4 int _class = Convert.ToInt32(Request.QueryString["c"]);
5
6 List<TestData> dataList = (List<TestData>)Session["TestData"];
7 dataList = dataList.FindAll(p => p.Class == _class); // 班级数据筛选
8 Session["TestData"] = dataList; // 更新 Session
9 }
10 protected void btnShowData_Click(object sender, EventArgs e)
11 {
12 List<TestData> dataList = (List<TestData>)Session["TestData"];
13 if (dataList != null)
14 {
15 ltlTestData.Text = TestData.ShowDataList(dataList);
16 }
17 }

问题:

若跳转到 _Class 页面后再跳转到 Grade.aspx 的话, Session["TestData"] 的数据与所期望的会不一样;
效果:

_Class.aspx?c=3

 点击下面的 Grade 跳转到 Grade.aspx 页面后 (本来没有 y 参数的 Grade.aspx 页面应该是显示所有的 TestData 数据才对):

原因分析: 因为在 _Class.aspx 页面已经将 Session["TestData"] 数据给更新了, 故跳转到 Grade.aspx 页面时使用的是更新了的 Session["TestData"];

 

解决方法: (1) 用不同的 Session 来记录数据, 比如 Session["Grade"], Session["Class"];
      如果这样的话, 页面多的时候会有很多个 Session, 管理起来比较麻烦, 很容易遗漏掉些什么东西, 而且这么一个错误, 也比较不容易发现, 很容易在哪里埋下地雷;
      (2) (我的方法) 按我的理解, Session 是用来记录页面状态的, 数据也算是状态的一部分, 但个人感觉不全, 比如: 导致上面错误的原因就是后面 Grade.aspx 页面所引用的 Session["TestData"] 记录的数据已经与它的状态不符了, 故: 如果在数据的记录里面, 多一个字段来作为页面与数据的过渡的话, 问题就解决了!

 

改进代码:

SessionTestData
1 public class SessionTestData : TestData
2 {
3 ///<summary>
4 /// 用来记录当前数据适合的页面地址
5 ///</summary>
6 public string URL { get; set; }
7 }

 

posted @ 2011-11-26 15:50  Howll Chen  阅读(263)  评论(0编辑  收藏  举报