简体   繁体   English

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

[英]C#/ASP.NET - Storing Generic List in Session VS Individual Variables in Session

I have seen many "wrapper" classes for the ASP.NET Session state and some do something like: 我已经看到了许多用于ASP.NET会话状态的“包装器”类,并且其中一些类似:

Strongly Typed Layer (Pseudo Code #1) 强类型层(伪代码#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}");

Then I have seen others do something like: 然后我看到其他人做了类似的事情:

Generic List Variant (Pseudo Code #2) 通用列表变体(伪代码#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}");
        ...
    }
}

Thoughts 思考

Obviously, these examples are both pseudo code style (so please ignore general errors), but they illustrate some of the approaches to building a data access layer for the Session state. 显然,这些示例都是伪代码样式(因此请忽略一般错误),但是它们说明了一些为Session状态构建数据访问层的方法。

I do something similar to the first variant, albeit, with a more comprehensive data type mapping/conversion plan. 尽管具有更全面的数据类型映射/转换计划,但我还是执行与第一个变体相似的操作。 I use a an "normal" class to wrap Session in, but it could easily be static since the properties will pull from the Session state when their "get" is called and thus never be out of sync since the class actually doesn't hold any data itself. 我使用一个“普通”类来包装Session,但是它很容易是静态的,因为属性将在调用它们的“ get”时从Session状态中拉出,因此永远不会不同步,因为该类实际上并不适用任何数据本身。

The second seems more "overkill" to me from first impressions since yes, you are only storing one variable in the Session state, but it clutters up the rest of the code by forcing code to be making references to the list: 从我的第一印象来看,第二个对我来说似乎更“矫kill过正”,因为是的,您只在Session状态下存储了一个变量,但是通过强制代码引用列表,使其余代码杂乱无章:

myObject.TheList.VariableIWant
VS
myObject.VariableIWant

of which I prefer the later (just looks cleaner), though this could easily be hidden in a super class or just making a local variable directly reference the list: 我更喜欢后者(看起来更干净),尽管可以很容易地将其隐藏在超类中或仅使局部变量直接引用该列表:

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

... though that looks kind of dirty to me at first glance. ...虽然乍一看对我来说似乎是肮脏的。 However, I don't know how much of a benefit using a list for storage actually gives to code/performance since storing an object that represents a list should take as much memory as doing each variable separately, at least that is my thinking. 但是,我不知道使用列表存储实际上对代码/性能有多大好处,因为存储代表列表的对象所需要的内存应与分别处理每个变量一样多,至少这是我的想法。


Question

Which is better practice / low maintenance in the long-term? 从长远来看哪个更好的实践/维护成本低? And/or Which gives better performance to the website? 和/或哪个可以使网站获得更好的性能?

Option #1 is the most common pattern that I see, and I use it. 选项#1是我看到的最常见的模式,我使用它。 You can improve it by using constants instead of magic strings. 您可以使用常量而不是魔术字符串来改进它。 Sessions have their issues, but so does making a completely stateless app. 会话有问题,但制作一个完全无状态的应用程序也有问题。 I also recommend using HttpCache instead of Session -- it will not consume AppPool resources. 我还建议使用HttpCache代替Session -它不会消耗AppPool资源。 But only Sessions can be used on a web farm, as long as you use a Session provider like SQL Server. 但是,只要您使用SQL Server等会话提供程序,就只能在Web场上使用会话。 Distributed caching is another matter. 分布式缓存是另一回事。

With option 1 it's really easy to tell what it's doing. 使用选项1,很容易分辨出它在做什么。 You're trying to standardize how your classes save/retrieve session data rather than scattering it all over the place. 您正在尝试标准化您的类如何保存/检索会话数据,而不是将其散布到各处。

Option 2 is a lot more confusing. 选项2更加令人困惑。 In fact I've looked it over a few times and I can't figure what's going on the list. 实际上,我已经看了好几次了,我无法弄清楚列表上的内容。 Why does option 2 require a list when option 1 doesn't? 为什么选项1不需要选项2时需要列表?

For what you're trying to do, option 1 works just fine. 对于您要尝试执行的操作,选项1很好用。 The constants aren't a bad idea, but in this one case I might skip it. 常量不是一个坏主意,但是在这种情况下,我可能会跳过它。 The meaning of the string is pretty obvious, and other classes won't need to duplicate it because they're going through this one to access Session. 字符串的含义非常明显,其他类不需要复制它,因为它们正在通过该类来访问Session。

Option #1 > Option #2 选项1>选项2

Two reasons: 两个原因:

  1. You should be deleting session variables as soon as you are done with them, using Session.Remove . 使用Session.Remove删除会话变量后,应立即删除它们。 Otherwise your session state will keep getting bigger and bigger and your web server won't be able to support as many simultaneous users. 否则,您的会话状态将越来越大,并且您的Web服务器将无法支持那么多同时用户。 But if all your variables are held in one big session variable, this is a bit harder to accomplish. 但是,如果所有变量都保存在一个大的会话变量中,则很难实现。

  2. I would avoid using reference types (eg a List of any kind) in session. 我会避免在会话中使用引用类型(例如,任何种类的List )。 It creates an ambiguity: if your session is stored in-proc, the session is only storing a pointer, and you can change session variables by changing the objects that they reference just like normal reference types. 它造成了歧义:如果您的会话存储在过程中,则该会话仅存储一个指针,并且您可以通过更改它们引用的对象更改会话变量,就像普通引用类型一样。 But if your session is out of proc (eg using state server or SQL state) then your objects will be serialized and frozen, and if you change the objects that are referenced, those changes will not get reflected in your session variables. 但是,如果您的会话超出proc(例如,使用状态服务器或SQL状态),则您的对象将被序列化和冻结,并且如果您更改所引用的对象,则这些更改将不会反映在您的会话变量中。 This could create all sorts of bugs that only appear on your upper environments (if your dev systems lack a state server) and drive you mad trying to troubleshoot. 这可能会造成各种错误,这些错误只出现在您的上层环境中(如果您的开发系统缺少状态服务器),并且使您疯狂地尝试进行故障排除。

    You could possibly make an exception for immutable reference types, but you'd have to be careful; 您可能会为不可变的引用类型设置一个例外,但是您必须要小心; just because an object is immutable doesn't mean the objects that it references are immutable too. 仅仅因为对象是不可变的,并不意味着它引用的对象也是不可变的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM