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

本文关键字:对象 LINQ 会话 存储 | 更新日期: 2023-09-27 18:30:34

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

因此,每当您需要引用客户对象时,都可以执行以下操作:

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

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

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

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

这不是

一个好主意。

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

就我个人而言,我更喜欢一种方法,将包含客户 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
 }

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

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

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