【问题标题】:Convert an ASP.net Singleton Session Instance to an object将 ASP.net 单例会话实例转换为对象
【发布时间】:2011-10-13 23:00:41
【问题描述】:

因此,我从另一位开发人员那里接手了一个 VB.net Web 应用程序项目,并发现迄今为止编写的代码存在一个明显的问题。

开发者根据本教程(http://net.tutsplus.com/tutorials/other/build-a-shopping-cart-in-aspnet/)构建了一个购物车应用程序。

注意:对于任何考虑将此作为生产 ASP.net 购物车的基础的开发人员 - 不要 - 继续阅读以了解更多信息......

编写该教程的人意识到,对于基于会话的购物车来说,使用 Singleton 并不是一个非常聪明的模式,但为时已晚。事实上,它很愚蠢——真的很愚蠢。使用这种模式,每个用户都有相同的购物车实例!

教程中有许多有用的 cmets 介绍了如何将 Singleton 实例会话转换为对象(例如作者:http://net.tutsplus.com/tutorials/other/build-a-shopping-cart-in-aspnet/comment-page-1/#comment-56782)。

但我的应用程序使用 VB.net 等效项(可在该页面上的下载文件中获得),我想知道我是否需要遍历整个应用程序并删除对以下内容的所有引用:

ShoppingCart.Instance.AddItem

并手动将它们替换为:

Dim cart As ShoppingCart = ShoppingCart.GetShoppingCart()

cart.AddItem(3)

或者有什么更聪明的方法可以转换这段代码:

#Region "Singleton Implementation"

' Readonly variables can only be set in initialization or in a constructor
Public Shared ReadOnly Instance As ShoppingCart
' The static constructor is called as soon as the class is loaded into memory
Shared Sub New()
    ' If the cart is not in the session, create one and put it there
    ' Otherwise, get it from the session
    If HttpContext.Current.Session("ASPNETShoppingCart") Is Nothing Then
        Instance = New ShoppingCart()
        Instance.Items = New List(Of CartItem)
        HttpContext.Current.Session("ASPNETShoppingCart") = Instance
    Else
        Instance = CType(HttpContext.Current.Session("ASPNETShoppingCart"), ShoppingCart)
    End If

换成别的东西,所以我不需要更改实例调用?

例如类似这样的东西(这是我在文章的另一条评论中找到的 C# 代码 sn-p - 我需要一个 VB.net 等价物,但我不知道如何编写它 - 我的 VB.net 有点生疏了! )

public static ShoppingCart Instance
{
    get
    {
        ShoppingCart c=null;
        if (HttpContext.Current.Session["ASPNETShoppingCart"] == null)
        {
            c = new ShoppingCart();
            c.Items = new List();
            HttpContext.Current.Session.Add(“ASPNETShoppingCart”, c);
        }
        else
        {
            c = (ShoppingCart)HttpContext.Current.Session["ASPNETShoppingCart"];
        }
        return c;
    }
}

感谢您提供的任何帮助。

埃德

【问题讨论】:

  • 有哪些存储选项?是全部在内存中还是由 SQL 等支持...?
  • @bryanmac 很公平 :) 我不是故意不接受答案。
  • @bryanmac - 我被 Inproc(内存)卡住了 - 我有一个只支持 Inproc 的 CMS(它显然不能序列化会话数据)

标签: session singleton instance


【解决方案1】:

编辑:

如果您执行上述代码,则无需更改实例调用。在大多数实例调用中,如果为 null,它们会创建静态对象并将其填充到静态成员变量中,并继续将同一个对象分发出去(可能会进行一些双重锁定检查)。在上面的代码中,您没有这样做 - 您转身并在他们的会话状态字典中给出一个,这样每个人都会得到一个不同的。

在这种情况下,术语实例会有点误导,但您不必更改所有调用代码。从逻辑上讲,这将是他们购物车的一个实例。

...

使用 HttpContext.Current.Session 字典将允许您将购物车存储在每个购物用户的内存中。

内存会话的缺点是如果 IIS 应用程序池回收,它将消失。此外,如果您必须添加另一个 Web 服务器(横向扩展),您将需要使用 NLB 亲和性——它只会限制您的选择。您的记忆力也会增加,因为他们的购物车会在会话的整个生命周期内一直保留在内存中 - 但这对于购物网站来说是一个很好的问题 :) 但是,它非常简单且重量轻。

其他选项是通过配置将会话状态存储在数据库中或滚动您自己的购物车表。

另一种选择是使用云存储——比如 Azure 表服务。这样你就可以两全其美——你不必维护你的 SQL 服务器,你可以在回收利用等方面获得冗余和持久性……嘿——你可以同时使用新技术 :)

【讨论】:

  • 完美@bryanmac - 看到我接受答案 - 当他们和你的一样好时:)
  • :) 谢谢 - 我通常会回答,但我希望能帮助人们。有些人没有意识到..
【解决方案2】:

使用此代码

公共静态 ShoppingCart 实例 { 得到 {

        if (HttpContext.Current.Session["ASPNETShoppingCart"] == null)
        {

            // we are creating a local variable and thus

            // not interfering with other users sessions

            ShoppingCart instance = new ShoppingCart();

            instance.Items = new List<CartItem>();

            HttpContext.Current.Session["ASPNETShoppingCart"] = instance;

            return instance;

        }
        else
        {

            // we are returning the shopping cart for the given user

            return (ShoppingCart)HttpContext.Current.Session["ASPNETShoppingCart"];

        }

    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多