【问题标题】:Session gets updated when the linked variable is updated更新链接变量时会更新会话
【发布时间】:2012-06-27 01:05:29
【问题描述】:

我在这里看到了很多关于在会话中存储列表然后检索它们的帖子。大多数答案都遵循这种技术:

if(Session["Strings"]==null)
{
      //Create List
      List<string> strings = new List<string>();
      ...
      Session["Strings"] = strings;
}
else
      strings =   Session["Strings"] as List<string>

//Add item to list
strings.Add("asdf");

我已经尝试过了,但是一旦我更新列表,会话变量也会更新,并且在回发时我会在会话中获得更新的值。这是预期的行为吗?如何使用它以使会话不更新?我什至尝试在使用后将“字符串”变量设置为 null,但会话在每次回发时仍有添加的项目。

也许我可以添加一些具体的代码来解释。

假设我的页面上有一个按钮点击事件:

     protected void GoClicked(object sender, EventArgs e)
 {

    List<string> a;
    if(Session["data"] == null)
    {
        a = new List<string>();
        a.Add("abc");
        a.Add("def");
        a.Add("ghi");

        Session["data"] = a;
    }
    else
    {
        a = (Session["data"] as List<string>);
    }
    a.Add("jkl");
    foreach (string s in a)
    {
        lblTest.Text += s + "<br />";
    }
}

每次单击按钮时,我都应该期望 'a' 仅包含 4 个值,因为我从 Session 中获取它并且它是一个局部变量。但实际上每次单击它时,都会添加值“jkl”,因此值的数量会不断增加。我不希望这种情况发生。我希望我更清楚。

【问题讨论】:

  • 这是使用 In-Proc Session 还是 Out-Proc?我想知道 Out-Proc 是否会发生这种情况?

标签: asp.net session-state


【解决方案1】:

我认为 ViewState 是您搜索的那个。尝试将它们保留在 ViewState 上以将此变量保留在页面内。这是您可以使用的代码:

const string _cListWStringsName = "cListWStrings_cnst";

public List<string> cListWStrings
{
    set
    {
        ViewState[_cListWStringsName] = value;
    }
    get
    {
        if (ViewState[_cListWStringsName] is List<string>)
        {
            return (List<string>)ViewState[_cListWStringsName];
        }
        else
        {
            var NewOne = new List<string>();

            ViewState[_cListWStringsName] = NewOne;

            return NewOne;
        }
    }
}

【讨论】:

  • 您的代码与我发布的代码相似,只是您使用的是 ViewState 并定义了一个属性。我也尝试过使用 ViewState - 一旦变量“字符串”更新,它也会更新。我认为这与 'strings' 作为 ref 类型有关。当我使用一个简单的整数时它工作正常。
【解决方案2】:

第一次单击按钮时,会添加四个值“abc”、“def”、“ghi”和“jkl”。并且在每次连续点击时都会添加“jkl”,因为 a.Add("jkl") 位于 if 子句之外。你需要把它移到 if 子句中,这里是:

 protected void GoClicked(object sender, EventArgs e)
 {

    List<string> a;
    if(Session["data"] == null)
    {
        a = new List<string>();
        a.Add("abc");
        a.Add("def");
        a.Add("ghi");
        a.Add("jkl");//Move here
        Session["data"] = a;
    }
    else
    {
        a = (Session["data"] as List<string>);
    }

    foreach (string s in a)
    {
        lblTest.Text += s + "<br />";
    }
} 

*更新:*Session 持有对 List 的引用,a 也是如此。两者都引用同一个列表,因此如果您在会话或会话中进行更改,引用的列表将被更改。请记住,Session 存储的是引用而不是值。现在,为什么“ijk”不断添加?因为列表永远不会超出范围(即使在您的方法完成执行之后),只要 Session 存在,它就会一直存在,所以当您的代码将“ijk”添加到“a”时,它实际上会将值添加到列表中。所以它不断将值“ijk”添加到 Session 引用的列表中。

【讨论】:

  • 不,这违背了目的。我可以很容易地在 Page_Load 中有初始化代码,并在按钮单击中添加一个项目代码。它应该在这两种情况下都有效。更新变量时不应更新会话
  • 请看一下更新后的答案。我很确定,它将消除您的疑虑并解决您的问题。
  • 如果我帮助了您,请标记您的问题已回答。谢谢。
猜你喜欢
  • 1970-01-01
  • 2011-12-05
  • 1970-01-01
  • 2014-05-17
  • 2011-02-08
  • 2018-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多