【问题标题】:How to change Replace an Object's Variable using Session in ASP.NET C#如何在 ASP.NET C# 中使用 Session 更改替换对象的变量
【发布时间】:2012-10-20 18:10:24
【问题描述】:

我想弄清楚如何通过网络浏览器更改客户的订单。客户将订购带有产品 ID(键)、产品名称、产品价格和他想要的数量的项目。 我想知道如何通过用不同数量的相同物品替换旧数量的旧物品来更改他的订单所以基本上点击选择物品并放置他希望的 2 个不同数量购买。购物车包含购买的物品,所以我想知道如何从购物车中销毁 OrderItem 然后重新创建它。

当我的代码找到购物车中已经存在的密钥时,需要将其销毁并使用新的 Quantity(来自网络应用程序的文本框)重新创建。

  protected void btnOrder_Click(object sender, EventArgs e)
{
    //Check for Shoppingcart object
    // Create first if not there
    if (Session["cart"] == null)
        Session["cart"] = new ShoppingCart();
    int quantity = 0;

    // make sure there is text
    if (txtQuantity.Text.Trim().Length != 0)
    {
        quantity = int.Parse(txtQuantity.Text);

        if (((ShoppingCart)Session["cart"]).
            keyExists(int.Parse(productID.Text)))
        {
        //Here I should Destroy the current item that exists and replace with new one

        }
        else  // This is a new item
        {
            // Make the item
            OrderItem item = new OrderItem(
                int.Parse(productID.Text), productName.Text,
                double.Parse(productPrice.Text),
                int.Parse(txtQuantity.Text));
            // add to cart  
            ((ShoppingCart)Session["cart"]).addToCart(item);

        }
        // How does this work? Who is sender?
        this.btnReturn_Click(sender, e);
    }
    else
    {
        Response.Write("Nothing Ordered<br>You must order some of the product or return to the Catalog");
    }

这里是 OrderItem 对象

public class OrderItem
{
private int productID;
private string prodName;
private double unitPrice;
private int quantityOrdered;

private string exceptionStr;


public OrderItem(int id, string name, double price, int quantity)
{
    prodName = name;
    exceptionStr = "Numeric data must not be negative";
    if ( id < 0 || price < 0 || quantity < 0)
    {
        throw new System.ArgumentException(exceptionStr);
    }
    else
    {
        productID = id;
        unitPrice = price;
        quantityOrdered = quantity;
    }
}


#region Public Properties
public int ProductID
{
    get
    {
        return productID;
    }
}

public string ProductName
{
    get 
    {
        return prodName;
    }
}


public double UnitPrice
{
    get
    {
        return unitPrice;
    }
}


public int QuantityOrdered
{
    get
    {
        return quantityOrdered;
    }
    set
    {
        if( value < 0 )
        {
            throw new ArgumentException(exceptionStr);
        }
        else
        {
            quantityOrdered = value;
        }
    }
}

#endregion
}

这是供您查看的购物车:

 public class ShoppingCart : IEnumerable
 {
private SortedList theCart;

public ShoppingCart() {
    theCart = new SortedList();
} // end of Constructor


public bool HasItems {
    get{
        bool hasItems = false;
        if( theCart.Count > 0 )
            hasItems = true;
        return hasItems;
    }
    set {
        // ignore this is read only
    }
} // end of HasItems


public void addToCart(OrderItem item) {
    theCart.Add(item.ProductID, item);
}// AddToCaArt

/// <summary>
/// deletes item that is passed
/// </summary>
/// <param name="item"></param>
public void deleteFromCart(OrderItem item)
{
    theCart.Remove(item.ProductID);
} // end deleteFromCart

/// <summary>
/// deletes the item with this id key
/// </summary>
/// <param name="id"></param>
public void deleteFromCart(int id)
{
    theCart.Remove(id);
} // end deleteFromCart
public OrderItem[] getCartContents()
{

// need to create stuff
    OrderItem[] stuff = null;
    theCart.Values.CopyTo(stuff, 0);

    return (stuff);
} // end getCartContents


public bool keyExists(int ID) {

    return theCart.ContainsKey(ID);
}// end keyExists

public ICollection Values
{
    get
    {
        return theCart.Values;
    }
}

#region IEnumerable Members

public IEnumerator GetEnumerator()
{
    return theCart.GetEnumerator();
}

#endregion
}

【问题讨论】:

  • ShoppingCartaddToCart 添加的)中存储了哪种类型的集合?
  • 你能发布 OrderItem 和 ShoppingCart 类型代码吗?
  • 它们是SortedLists,addToCart将productID和客户选择的item添加到SortedList名称theCart中,ShoppingCart和OrderItem的code就起来了。
  • 除非您再次销毁并存储,否则您无法更改存储在会话中的对象的变量。
  • 此外,当您完成解决方案后,请尝试将您的代码发布到 codereview.stackexchange.com... 在我看来,设计和代码风格需要许多改进。

标签: c# asp.net session


【解决方案1】:

我强烈建议从类或模型级别考虑购物车的外观。我认为像下面这样的一组类将有很大帮助(不是最好的,但从头开始设计还不错):

[Serializable]
public class ShoppingCartItem
{
  public ShoppingCartItem(guid key, decimal price, int quantity)
  {
    this.Key = key;
    this.Price = price;
    this.Quantity = quantity;
  }

  public Guid Key { get; private set; }
  public Decimal Price { get; private set; }
  public int Quantity { get; set; }
}

[Serializable]
public class ShoppingCart
{
  public ShoppingCart()
  {
    this.Clear();
  }

  public ICollection<ShoppingCartItem> Items { get; private set; }

  public int ItemCount 
  {
    get { return this.Items.Sum(i => i.Quantity); }
  }

  public decimal Subtotal
  {
    get { return this.Items.Sum(i => i.Quantity * i.Price); }
  }

  public void Clear()
  {
    this.Items = new List<ShoppingCartItem>();
  }
}

现在 ShoppingCart 可以序列化,以便能够存储在 ASP.Net 会话中(或制作愿望清单 :))

现在我不喜欢松散类型的 ASP.Net 会话,所以我从一些我不记得的地方借用了这个很棒的类来制作强类型的 Session 对象:

using System;
using System.Web;

namespace Company.Product.Web.UI.Domain
{
    public abstract class SessionBase<T> where T : class, new()
    {
        private static readonly Object _padlock = new Object();

        private static string Key
        {
            get { return typeof(SessionBase<T>).FullName; }
        }

        public static T Current
        {
            get
            {
                var instance = HttpContext.Current.Session[Key] as T;

                if (instance == null)
                {
                    lock (SessionBase<T>._padlock)
                    {
                        if (instance == null)
                        {
                            HttpContext.Current.Session[Key] = 
                              instance = new T();
                        }
                    }
                }

                return instance;
            }
        }

        public static void Clear()
        {
            var instance = HttpContext.Current.Session[Key] as T;
            if (instance != null)
            {
                lock (SessionBase<T>._padlock)
                {
                    HttpContext.Current.Session[Key] = null;
                }
            }
        }

    }
}

为了在这个例子中使用它,我将创建:

public class ShoppingCartSession : SessionBase<ShoppingCart> { }

然后我可以在我的代码中的任何地方使用它:

var item = ShoppingCartSession.Current.Items.FirstOrDefault(i => i.Key= key);

if (item == null)
{
  ShoppingCartSession.Current.Items.Add(
    new ShoppingCartItem(Key, price, quantity));
}
else
{
  item.Quantity = item.Quantity + quantity;
}

强类型会话购物车对象,可扩展,允许您做任何您想做的事以及更多。应用程序的其他部分也可以访问它,以显示购物车中的商品数量和某个区域的小计,例如在应用程序顶部显示购物车状态的小预览。

【讨论】:

    【解决方案2】:

    在您的ShoppingCart 类中,您可以添加一个名为IncreaseQuantity(int productID) 的方法(和一个DecreaseQuantity 方法)。

    public void IncreaseQuantity(int productID)
    {
       int indexOfProduct = theCart.IndexOfKey(productID);
    
       if(indexOfProduct != -1)
       {
           this.theCart[indexOfProduct].quantityOrdered++;
       }
    }
    

    然后从你的会话中调用方法

    ShoppingCart cart = (ShoppingCart)Session["cart"];
    
    if (cart.keyExists(int.Parse(productID.Text)))
    {
        //can store the parsed int in a variable instead to prevent...
        //having to parse twice.
        cart.IncreaseQuantity(int.Parse(productID.Text));    
    }
    

    【讨论】:

      【解决方案3】:

      我认为没有办法。

      是什么让您需要重新创建对象?
      是性能,还是保持代码干净?

      如果是性能问题:
      考虑为每个项目在 Session 上保存一个单独的对象,就像这样 -

      int itemID = int.Parse(productID.Text);
      int productQuantity = Session["item_number_" + itemID];
      

      如果这是保持代码清洁的问题:
      考虑将所有Session 逻辑放在一个属性中:

      public ShoppingCart SessionCart
      {
          get
          {
              if (Session["cart"] == null)
                  return new ShoppingCart();
              else
                  return (ShoppingCart)Session["cart"];
          }
          set
          {
              Session["cart"] = value;
          }
      }
      

      【讨论】:

        【解决方案4】:

        一种方法是将数量保持为每个 OrderItem 的一部分,然后通过枚举每个单独的 OrderItem 数量来获取购物车的总数。但是每个 OrderItem ID 必须只出现一次 ShoppingCart。

        例如,在 ShoppingCart 中添加一个方法

            public OrderItem Retrieve(int id)
            {
                return theCart[id] as OrderItem;
            }
        

        然后如果购物车已经包含相同的产品 ID

            OrderItem orderItem = cart.Retrieve(1);
            item.QuantityOrdered += 1;
        

        最后将更新后的购物车对象赋值给 Session 变量。

        另一种实现方式是在 ShoppingCart 中添加另一个 OrderItem 并维护按 OrderItem Id 分组的计数

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-10-14
          • 2015-06-27
          • 2012-01-31
          • 2020-11-20
          • 2011-10-23
          • 1970-01-01
          • 2019-04-22
          • 2023-03-22
          相关资源
          最近更新 更多