如果是第二种情况,其实也不见得好到哪里去。因为:
1、currentUser可能不需要经常取,但相关的其它内容,由于上下文各自独立,你还是经常在重复的获取的;
2、有一个地方你无法绕过去——如果你要修改当前用户的属性,而这个全局的当前用户不是当前Context产生的,你还非得从当前Context取出来,然后再修改;
3、因为currentUser的上下文已经被抛弃了,因此程序会很容易设计成传入的不是一个UserInfo,而是一个int类型的Id值,否则底层很容易一不小心就用到这个实际上功能不全的对象,然后就抛出异常了。但这样做的后果是,获取同一个类型的实体对象,可能会有各种不同的重载形式,例如:
IQueryable<TransactionInfo> GetTransactionsByUserId(int userId);
IQueryable<TransactionInfo> GetTransactionsByCompanyId(int companyId);
IQueryable<TransactionInfo> GetTransactionsByCompanyId(int companyId);
因为这种设计实施之后,有时很可能就会出现只有userId的情况,那么这个时候即使UserInfo对象中其实也存在CompanyId的值,也还是要重新获取一遍UserInfo对象。为了简化这一过程,就可能会产生不同的获取形式。
这样设计完整个系统之后一跑,看着好像没什么,但真正上线却发现有点慢。当我们打开Sql server的Profiler一看,会发现很简单的一个页面的访问,其数据库访问会搞到几十次甚至上百次,其中有很多Sql语句是完全重复的。
这个问题怎么解决呢?有人会说,加个缓存机制吧。也许吧,但这种增加复杂度的设计,我觉得还是不得已而为之的一种做法。我认为更好的解决办法是,将上下文在当前页面中缓存起来。所谓的上下文,就是一种运行环境,而一次页面访问,其环境应该是相同的。首先,我们对MyDataContext做一个扩展:
partial class MyDataContext
{
private const string c_KeyCurrentHttpContext = "chctx";
static public MyDataContext CurrentHttpContext
{
get
{
MyDataContext context = CurrentHttpContextWeak;
if (context == null)
{
context = new MyDataContext();
CurrentHttpContextWeak = context;
}
return context;
}
}
static private MyDataContext CurrentHttpContextWeak
{
get
{
return HttpContext.Current.Items[c_KeyCurrentHttpContext] as MyDataContext;
}
set
{
HttpContext.Current.Items[c_KeyCurrentHttpContext] = value;
}
}
static internal void TryDisposeCurrentHttpContext()
{
MyDataContext context = CurrentHttpContextWeak;
if (context != null)
{
context.Dispose();
CurrentHttpContextWeak = null;
}
}
}
{
private const string c_KeyCurrentHttpContext = "chctx";
static public MyDataContext CurrentHttpContext
{
get
{
MyDataContext context = CurrentHttpContextWeak;
if (context == null)
{
context = new MyDataContext();
CurrentHttpContextWeak = context;
}
return context;
}
}
static private MyDataContext CurrentHttpContextWeak
{
get
{
return HttpContext.Current.Items[c_KeyCurrentHttpContext] as MyDataContext;
}
set
{
HttpContext.Current.Items[c_KeyCurrentHttpContext] = value;
}
}
static internal void TryDisposeCurrentHttpContext()
{
MyDataContext context = CurrentHttpContextWeak;
if (context != null)
{
context.Dispose();
CurrentHttpContextWeak = null;
}
}
}