在数据访问层中访问HttpContext.Current

时间:2011-01-06 07:15:12

标签: architecture entity-framework-4 repository httpcontext objectcontext

基于我在Entity Framework in layered architecture的问题的答案,现在我想将我的存储库(现在只负责CRUD抽象,而不是业务逻辑的东西)移动到DAL并为业务逻辑保留BLL 。
我得出的结论是,实体上下文应该被视为一个工作单元,因此不能重复使用。因此,我想在我的存储库中为每个HttpContext创建一个obejctcontext,以防止性能/线程[un]安全问题。我想在存储库中定义objectcontext,如下所示:

public MyDBEntities ctx
    {
        get
        {
            string ocKey = "ctx_" + HttpContext.Current.GetHashCode().ToString("x");
            if (!HttpContext.Current.Items.Contains(ocKey))
                HttpContext.Current.Items.Add(ocKey, new MyDBEntities ());
            return HttpContext.Current.Items[ocKey] as MyDBEntities ;
        }
    }

在这种情况下,DAL项目应该知道HttpContext.Current变量。我不确定这是不是一个好习惯,并且想知道你的意见。

1 个答案:

答案 0 :(得分:2)

不在Web应用程序之外访问HttpContext是不好的做法,因为它将您的代码紧密地耦合到Web环境。你正在寻找的可能是每个HTTP请求对象生命周期管理器反转控制容器。

假设您将业务逻辑定义为:

public class BusinessService : IBusinessService
{ 
  // Constructor with dependency injection
  public BusinessService(IObjectContext context)
  { ... }

  ...
}

现在,当您想要使用BusinessService时,您必须创建其实例并将其作为参数传递给IObjectContext。使用控件容器的反转时,您可以利用此定义而不是构造函数调用类似:

IBusinessService service = container.Resolve<IBusinessService>();

控制反转(IoC)容器必须配置为能够实例化IBusinessService和IObjectContext的具体实现。此外,此配置通常允许定义实例化对象的生命周期。当允许每个HTTP生存期时,在单个请求中对Resolve的每次调用都会返回相同的实例。

通过让容器使用您的业务服务解决课程,您可以更进一步。通常使用ASP.NET MVC完成。在这种情况下,您只定义在主类(控制器)中接收服务作为参数的构造函数,并让IoC容器构建整个对象层次结构。

对于控制容器的反转,请检查例如Windsor Castle。我正在使用MS Unity,但它没有为每个HTTP生命周期管理器提供开箱即用的功能。