我想获得一些关于将整个对象存储到会话中的想法的反馈?例如,客户对象。一旦客户登录其控制面板,而不是每次需要从会话中存储的ID重新获取数据时,将整个客户对象存储在会话中的优缺点是什么?
因此,只要您需要引用客户对象,您就可以这样做:
Customer c = (Customer)Session["objCustomer"];
显然,你需要检查并拥有一个刷新会话的功能。您需要在空会话或更新后运行此函数。
除此之外,还有其他问题我应该注意这样做吗?就编程而言,这似乎会好得多,而且对数据库的调用也要少得多。有谁想?
答案 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我同意你引入所需属性的观点。你可以通过调整模型来做到这一点,你也可以关闭延迟加载。除此之外,我认为这是非常安全的。除非我们将所有这些对象存储为引用,否则这些对象一旦置于会话中就没有问题。唯一可能导致问题的是两个上下文都在范围内。