3

我想就您将整个对象存储到会话中的想法获得一些反馈?例如,客户对象。一旦客户登录到他们的控制面板,而不是每次需要从会话中存储的 ID 重新获取他们的数据,将整个客户对象存储在会话中的优缺点是什么?

因此,只要您需要引用客户对象,您就可以这样做:

Customer c = (Customer)Session["objCustomer"];

显然,您需要检查并具有刷新会话的功能。在空会话的情况下或进行更新后,您需要运行此函数。

除此之外,还有其他我应该注意的问题吗?就编程而言,这似乎要好得多,而且对数据库的调用也少得多。有人想吗?

4

3 回答 3

7

这不是一个好主意。

主要原因是 ORMappers 的工作方式 - 当您混合来自不同上下文的对象时,它们不喜欢它。这将在您建议的场景中发生 - 您在会话中有一个对象,由您的下一个(和后续)请求使用的不同上下文创建。Sonner 或以后你会开始遇到异常。

就我个人而言,我更喜欢一种方法,其中包含客户 ID(可能还有其他属性)的简单对象存储在会话中(或表单 cookie 的自定义数据部分),我将对客户对象的访问包装在一个简单的语句中涉及Items容器:

(生产代码需要在这里和那里进行一些检查才能更具防御性):

const string CUSTOMERITEM = "customeritem";
public Customer Current
{
    get
    {
        if ( HttpContext.Current.Items[CUSTOMERITEM] == null )
        {
           int id = retrieve_the_id;

           using ( DbContext ctx = GetCurrentDbContext() ) 
           {
               HttpContext.Current.Items.Add( CUSTOMERITEM, ctx.Customers.FirstOrDefault( c => c.ID == id );
           }
        }
        return (Customer)HttpContext.Current.Items[CUSTOMERITEM];
    }
}

项目容器仅持续一个请求的时间。上面的代码片段确保每个请求只加载一次对象。

当然,与您的方法相比,每个请求需要额外查询一次。但优点是您永远不会弄乱数据库上下文。

请注意,有些业务流程不需要该Customer对象,但您可以直接传递客户 ID 并在查询中使用:

 public IEnumerable<Order> CustomerOrders( int CustomerID ) 
 {
     // use the customer id directly, without first loading the customer object
 }
于 2012-04-09T14:53:26.317 回答
2

我在另一个答案中遇到了 Wiktor 描述的问题。我使用 NHibernate,如果您将对象存储在会话中,您会遇到比较它们的问题、断开会话的问题等。尽管如此,我还是将对象存储在会话中。我只是确保他们都实现了自己的 Equals() 和 GetHashCode() 函数。这样我就可以比较来自不同会话的对象,看看它们是否是同一个对象。我养成了使用obj1.Equals(obj2)而不是obj1 == obj2.

当然,总会有权衡——您获得了不必重复查询的速度,而不是增加代码的复杂性。哪种方式适合您取决于您​​的具体情况。

于 2012-04-09T14:59:38.227 回答
0

mellamokb 我同意你引入你需要的属性的观点。你可以通过调整模型来做到这一点,你也可以关闭延迟加载。除此之外,我认为这是非常安全的。除非我们将所有这些对象存储为引用,否则这些对象一旦放置在会话中就没有问题。唯一可能导致问题的情况是两个上下文都在范围内。

于 2012-04-09T16:12:18.837 回答