C#/ ASP.NET - 在会话中存储通用列表VS在会话中的单个变量

时间:2017-05-08 22:43:00

标签: c# asp.net session model-view-controller

我见过很多"包装" ASP.NET会话状态的类和一些类似的东西:

强类型图层(伪代码#1)

public class MySession
{
    public int MyID
    {
        get
        {
            return Convert.ToInt32(HttpContext.Current.Session["MyID"]);
        }
        set
        {
            HttpContext.Current.Session["MyID"] = value;
        }
    }
    public string MyName
    {
        get
        {
            return (HttpContext.Current.Session["MyName"]).ToString();
        }
        set
        {
            HttpContext.Current.Session["MyName"] = value;
        }
    }
    ...

    public MySession()
    {
        // Could be static or instantiated depending on needs...
    }
    ...
}

///// USAGE IN OTHER CLASS /////

MySession currSession = new MySession();
currSession.MyID = 5;
currSession.MyName = "John Doe";

Console.WriteLine($"{currSession.MyName}'s ID = {currSession.MyID}");

然后我看到别人做了类似的事情:

通用列表变体(伪代码#2)

public class SessionVariables
{
    public int MyID
    {
        get;
        set
        {
            MyID = value;
            MySession.SaveVariables();
        }
    }
    public string MyName
    {
        get;
        set
        {
            MyName = value;
            MySession.SaveVariables();
        }
    }

    ...
}

public class MySession
{
    public static List<SessionVariables> Variables;

    // Might be private in real application environment
    public MySession() // Could be static or instantiated depending on needs...
    {

        if (HttpContext.Current.Session["MyVariables"] == null)
        {
            HttpContext.Current.Session["MyVariables"] = new List<SessionVariables>();
        }

        // Obviously more appropriate checking to do here, but for simplicity's sake...
        Variables = (List<SessionVariables>)HttpContext.Current.Session["MyVariables"]

    }

    public static void SaveVariables()
    {
        HttpContext.Current.Session["MyVariables"] = Variables;
    }
    ...
}

///// USAGE /////

public class MyPage
{
    public void MyMethod()
    {
        MySession currSession = new MySession(); // Create variables

        MySession.Variables.MyID = 5;
        MySession.Variables.MyName = "John Doe";
        Console.WriteLine($"{MySession.Variables.MyName}'s ID = {MySession.Variables.MyID}");
        ...
    }
}

思想

显然,这些示例都是伪代码样式(因此请忽略一般错误),但它们说明了为会话状态构建数据访问层的一些方法。

我做了类似于第一个变体的事情,尽管有更全面的数据类型映射/转换计划。我使用正常的&#34;用于包装Session的类,但它很容易是静态的,因为当它们的&#34; get&#34;时,属性将从Session状态拉出。被调用,因此永远不会失去同步,因为类本身实际上并不保存任何数据。

第二个似乎更多&#34;矫枉过正&#34;从第一印象开始,对我来说,你只是在Session状态中存储一个变量,但它通过强制代码引用列表来混淆其余的代码:

myObject.TheList.VariableIWant
VS
myObject.VariableIWant

我更喜欢后者(看起来更干净),虽然这可以很容易地隐藏在超级类中,或者只是让局部变量直接引用该列表:

new MySession(); // Create the variables
List<SessionVariables> mySession = MySession.Variables;

......乍一看,这看起来很脏。但是,我不知道使用存储列表实际上给代码/性能带来了多少好处,因为存储表示列表的对象应该占用与单独执行每个变量一样多的内存,至少这是我的想法

问题

长期来看哪种做法更好/维护费用更低?和/或哪个会给网站带来更好的表现?

3 个答案:

答案 0 :(得分:0)

选项#1是我看到的最常见的模式,我使用它。您可以使用常量而不是魔术字符串来改进它。会话有他们的问题,但制作一个完全无状态的应用程序也是如此。我还建议使用HttpCache而不是Session - 它不会消耗AppPool资源。但只有使用像SQL Server这样的会话提供程序,才能在Web场中使用Sessions。分布式缓存是另一回事。

答案 1 :(得分:0)

使用选项1,它很容易分辨出它在做什么。您正在尝试标准化类如何保存/检索会话数据,而不是将其分散到各处。

选项2更令人困惑。事实上,我已经看了好几次,但我无法确定列表上的内容。为什么选项2在选项1没有?

时需要列表

对于您尝试做的事情,选项1工作得很好。常数并不是一个坏主意,但在这种情况下我可能会跳过它。字符串的含义非常明显,其他类不需要复制它,因为它们通过这个类来访问Session。

答案 2 :(得分:0)

选项#1&gt;选项#2

有两个原因:

  1. 您应该在使用Session.Remove后立即删除会话变量。否则,您的会话状态将越来越大,您的Web服务器将无法支持尽可能多的并发用户。但是如果你的所有变量都保存在一个大的会话变量中,那就更难实现了。

  2. 我会避免在会话中使用引用类型(例如任何类型的List)。它会产生歧义:如果你的会话存储在-proc中,那么会话只存储一个指针,你可以change session variables by changing the objects that they reference就像普通的引用类型一样。但是如果您的会话超出了proc(例如使用状态服务器或SQL状态),那么您的对象将被序列化并冻结,如果您更改引用的对象,那些的更改将反映在你的会话变量。这可能会产生各种错误,这些错误只会出现在您的上层环境中(如果您的开发系统缺少状态服务器)并让您疯狂尝试进行故障排除。

    您可能会为不可变引用类型创建一个例外,但您必须小心;仅仅因为对象是不可变的并不意味着它引用的对象也是不可变的。