在asp.net会话中存储不同的数据类型

时间:2017-07-16 16:00:12

标签: c# asp.net session session-variables

与同事聊天后,我有兴趣知道是否有人做过任何研究/测试,以便在asp.net会话中查看最有效和推荐的数据存储方式。

我最近偶然发现了这个问题:How to access session variables from any class in ASP.NET?并开始使用该技术(创建我自己的会话类,以便给我智能感知的优势,并防止在从会话中检索数据时需要显式转换)。

但是,有人建议将我的对象中的数据序列化为字符串然后存储...然后在检索时反序列化,这可能效率不高。

例如......如果我想加载用户的当前权限并将其存储在会话中;我的会话对象中可能有一个属性定义为List<int> user_permissions,然后在每个页面上if (session_class.user_permissions.contains(7))

或者,我可以直接在会话中存储类似的字符串; HttpContext.Current.Session["user_permissions"] = "[1][4][8][12]"然后在每个页面上我都可以查看HttpContext.Current.Session["user_permissions"].contains("[7]")

哪种选择更有效率,是否可以量化?

5 个答案:

答案 0 :(得分:1)

首先要确定ASP.NET能够开箱即用的序列化。由于ASP.NET参考源可用,我们可以将状态序列化深入到此类:AltSerialization

它表明本机支持以下类型:

String
Int32
Boolean
DateTime
Decimal
Byte
Char
Single
Double
SByte
Int16
Int64
UInt16
UInt32
UInt64
TimeSpan
Guid
IntPtr
UIntPtr
Null // not really a type :-)

对于所有其他类型,系统使用BinaryFormatter,这是一个公共.NET类。 BinaryFormatter非常易于使用,默认情况下它知道许多类,因此您可以比较BinaryFormatter将生成的内容与您自己“手动”的内容进行简单的基准测试。

通常,您总是能够击败BinaryFormatter的性能,因为您更了解数据,但这意味着您必须编写额外的序列化/反序列化代码。您还可以创建自定义类并实现ISerializable

最后一点,如果你看一下AltSerialization来源,你会看到:

internal static void WriteValueToStream(Object value, BinaryWriter writer)
{
    if (known type) { ... }
    else
    {
        ...
        var formatter = new BinaryFormatter();
        if (SessionStateUtility.SerializationSurrogateSelector != null)
        {
            formatter.SurrogateSelector = SessionStateUtility.SerializationSurrogateSelector;
        }

        formatter.Serialize(writer.BaseStream, value);
    }
}

这意味着你可以实现一个全局钩子来处理中心位置的特定类型,这在入门或基准测试方面很有用(你可以启用它或者很容易地禁用它)。它可能比创建可序列化的自定义类更好。

答案 1 :(得分:0)

假设您只在一台计算机上托管(因此会话状态不需要序列化到公共存储库),您可以使用通用的MemoryCache将会话数据托管在内存中,由唯一键入会话ID。

public class SessionData
{
    private static readonly MemoryCache Cache = new MemoryCache("SessionData");
    private static readonly CacheItemPolicy Policy = new CacheItemPolicy {SlidingExpiration = new TimeSpan(0, 30, 0)};

    public static SessionData Get(string sessionId)
    {
        if (Cache.Contains(sessionId))
            return Cache[sessionId] as SessionData;

        var item = new SessionData {SessionId = sessionId};
        Cache.Add(sessionId, item, Policy);
        return item;
    }

    public string SessionId { get; set; }
    public string Foo { get; set; }
    public int Bar { get; set; }
}

使用示例:

var item = SessionData.Get(this.Session.SessionID);
item.Foo = "Hello";
item.Bar = 123;

会话数据保存在内存中,滑动到期时间为30分钟 - 每次访问时都会重置30分钟超时。这样,您就不会因过期会话而遭受内存膨胀。根据当前的实现情况,看看它是如何叠加的。

答案 2 :(得分:0)

我在帖子中发现了两个问题。

<强> 1。在asp.net会话中存储不同的数据类型

您可能知道,在ASP.NET中保留Session有三种模式,如下所示:StateServerSqlServerInProc

SateServer模式下,您可以为会话的值设置任何对象而不进行序列化,因为会话和Web在同一个进程中运行。

但是对于其他方式,当值不是结构时,会话的值必须序列化。 SqlServerList.contains()在独立进程上运行(可能在独立服务器上),因此会话的值将被序列化并在您设置时保持另一个进程。

<强> 2。哪个选项更有效,是否可以在String.contains()contains量化?

如果您没有获得大数据,它们没有太大区别。每个都使用循环。如果您想在HashSet中提高效率,可以尝试$menuSet->GetMenuItems()

答案 3 :(得分:0)

实际上,问题在于您的方法的性能与您拥有可维护且可读的代码库的重要性有多重要?

对于您用于序列化和反序列化数据的框架也有所不同,可能值得对其进行一些基本的速度测试。如果你能在一秒钟内处理数千亿的请求,那可能就行了。

您明确询问&#34;哪个选项更有效,是否可以量化?&#34;是。绝对。只需设置一个StopWatch(参见System.Diagnostics我相信它)并使用一些测试数据多次调用该方法,然后检查秒表的时间。

P.S。您的问题表明关于这个Session类需要具体的性能的讨论...根据我的经验,在Web应用程序中,(de)序列化并不是主要关注的问题。它是数据库瓶颈和其他长时间运行的进程,它们会降低服务器速度。如果由于参数#34而询问了这个问题,那么服务器已经很慢了,所以这只是额外的......&#34;然后告诉他们解决其他问题,这就像把骆驼打破,因为它是真正做到的2吨砖的骆驼。只是预感到了这个论点:P

答案 4 :(得分:-1)

我认为我们已经提出了确定存储对象(特别是使用自定义类包装器技术How to access session variables from any class in ASP.NET?)的最佳方法。根据我们的理解,这将把类的所有属性(字段)存储在内存中,即使是空的。

public class my_session {
 public int iUserID;
 public string sUserName;
 public List<int> lsUSerPermissions;
 public List<TestStatus> lsTestStatuses;
 public int iSomethingElse;
 public bool bSomething;
}

即使我们不会填充/设置所有会话的所有属性,每个会话都将包含所有属性(并使用相关的内存)。最初我虽然这很奇怪,但现在我明白它是有道理的,所以如果/当你设置每个属性时,内存可用,并且对象不必被销毁并在其他地方重新创建。

如果我们直接分配,我们只需要为那些需要存储的属性创建会话变量。

所以,现在我们已经决定将这些单独存储起来;

Session["iUserID"] = 1;
Session["sUserName"] = "Lee";

我们如何处理我们必须&#34;商店? 看起来每个对象都需要单独查看。 string sUserPermissions = "[ViewUser][CreateUser][EditUser]"占用的内存是否少List<string> lsUserPermissions = new List<string>() { "[ViewUser]", "[CreateUser]", "[EditUser]" },如果需要,是否可以更快地序列化/反序列化?

还需要相当多的研究。