关于在会话中存储整个LINQ对象的想法?

时间:2012-04-09 14:37:13

标签: c# asp.net linq oop session

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

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

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

显然,你需要检查并拥有一个刷新会话的功能。您需要在空会话或更新后运行此函数。

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

3 个答案:

答案 0 :(得分: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
 }

答案 1 :(得分:2)

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

当然,总会有权衡 - 你不必重复查询,而不是在代码中获得复杂性。哪种方式适合您取决于您​​的具体情况。

答案 2 :(得分:0)

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