基于我在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变量。我不确定这是不是一个好习惯,并且想知道你的意见。
答案 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生命周期管理器提供开箱即用的功能。