然后我们再制作一个HttpModule(并且在web.config里面配置好):
/// <summary>
/// 实现自动抛弃当前数据库上下文的模块
/// </summary>
public class MyDataContextAutoDisposeModule : IHttpModule
{
#region IHttpModule Members
private HttpApplication _context;
public void Init(HttpApplication context)
{
_context = context;
context.PostRequestHandlerExecute += new EventHandler(context_PostRequestHandlerExecute);
}
void context_PostRequestHandlerExecute(object sender, EventArgs e)
{
MyDataContext.TryDisposeCurrentHttpContext();
}
#endregion
}
/// 实现自动抛弃当前数据库上下文的模块
/// </summary>
public class MyDataContextAutoDisposeModule : IHttpModule
{
#region IHttpModule Members
private HttpApplication _context;
public void Init(HttpApplication context)
{
_context = context;
context.PostRequestHandlerExecute += new EventHandler(context_PostRequestHandlerExecute);
}
void context_PostRequestHandlerExecute(object sender, EventArgs e)
{
MyDataContext.TryDisposeCurrentHttpContext();
}
#endregion
}
接下来,我们只要在逻辑层这么直接写即可:
public static IQueryable<TransactionInfo> GetCompanyAccountDetails(UserInfo operatorUser, EAccountName account)
{
// 权限验证
if (!operatorUser.Permissions.Contains(EUserPermissions.ViewAccountDetails))
CLog.CurrentHttpContext.ThrowFailedException(new CPermissionException(EUserPermissions.ViewAccountDetails));
var q = MyDataContext.CurrentHttpContext.TransactionInfos.Where(t => t.CompanyId == operatorUser.CompanyId && t.AccountName == account);
return q;
}
{
// 权限验证
if (!operatorUser.Permissions.Contains(EUserPermissions.ViewAccountDetails))
CLog.CurrentHttpContext.ThrowFailedException(new CPermissionException(EUserPermissions.ViewAccountDetails));
var q = MyDataContext.CurrentHttpContext.TransactionInfos.Where(t => t.CompanyId == operatorUser.CompanyId && t.AccountName == account);
return q;
}
这么改造完之后,你会发现几乎可以在所有地方直接返回IQueryable(除了有的时候Linq to Sql本身有Bug),整个逻辑层内的设计变得简单化:一开始检查各种参数(是否具备完整或者部分权限),然后根据检查结果做完全信赖的操作。由于返回的是实体对象,或者IQueryable,几乎所有重复性的Sql调用也随之自然消失了。如果有所怀疑的话,您可以用Sql Profiler自行做修改前后的对比,看看效果是否“惊人”?
也许有人会质疑,这样好吗?岂不是通过user.Company.Transactions就可以得到所有的Transaction了?没错,如果所有东西都是公开的话,就会有这个问题。如果要彻底解决这样的问题,需要将这些部分变成对逻辑层可见,而对其它层不可见的修饰方式——比如两层在一个dll里面,这些属性是internal的,或者放在两个dll里面并且打上InternalsVisibleTo标记。通过这种方式,就可以避免上层直接查找DAL中一些在BLL中需要经过权限检查才可以得到的内容。当然,如果项目比较小的情况下,你也可以选择不要这么麻烦,直接控制代码质量即可(要求有些东西必须通过BLL来获得)。