具有依赖注入的实体框架ObjectContext [英] Entity Framework ObjectContext with Dependency Injection
问题描述
- UI层:ASP.NET Webforms网站。
- BLL:在DAL上调用存储库的业务逻辑层。
- DAL:.EDMX文件(实体模型)和具有Repository类的ObjectContext,用于抽取每个实体的CRUD操作。
- 实体:POCO实体。持久性无知。由Microsoft的ADO.Net POCO实体生成器生成。
我想在我的存储库中为每个HttpContext创建一个obejctcontext,以防止性能/线程[un]安全问题。理想的情况是这样的:
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());
返回HttpContext.Current.Items [ocKey]作为MyDBEntities;
}
}
问题是我不想访问HttpContext在我的DAL(存储库所在的位置)。但是我必须以某种方式将HttpContext传递给DAL。根据我的问题的答案这里,我必须使用IoC模式。理想情况下,我想在多层架构中实现像这个这样的东西。
我已经检查了Autofac,这似乎非常有希望。 但是我不知道如何实现这一点(传递Httpcontext以确保一个ObjectContext在HttpContext中被实例化)在多层架构中。有人可以给我一些关于如何实现的工作示例吗?如何在DAL中不知道HttpContext,而不直接访问DAL中的HttpContext?我觉得我在设计一个多层次的解决方案中有些失落。
我从来没有使用IoC容器与WebForms所以得到这个一些高层次的解决方案,这可能会进一步改善。
您可以尝试创建一些IoC提供商作为单身人士:
public class IoCProvider
{
private static IoCProvider _instance = new IoCProvider();
私人IWindsorContainer _container;
public IWindsorContainer
{
get
{
return _container;
}
}
public static IoCProvider GetInstance()
{
return _instance;
}
private IoCProvider()
{
_container = new WindsorContainer(new XmlInterpreter(new ConfigResource(castle)));
}
}
您的 web.config
将必须包含以下部分(配置基于您的上一篇文章):
< configuration>
< configSections>
< section name =castletype =Castle.Windsor.Configuration.AppDomain.CastleSectionHandler,Castle.Windsor/>
< / configSections>
< castle>
< components>
< component id =DalLayer
service =MyDal.IDalLayer,MyDal
type =MyDal.MyDalLayer,MyDal
lifestyle =PerWebRequest>
<! -
这里我们定义DalLayer的生活方式是PerWebRequest,所以每个
时间容器在同一个Web请求
处理中解析IDalLayer接口,它返回相同的实例DalLayer类
- >
< parameters>
< connectionString> ...< / connectionString>
< / parameters>
< / component>
< component id =BusinessLayer
service =MyBll.IBusinessLayer,MyBll
type =MyBll.BusinessLayer,MyBll/>
<! -
只是BusinessLayer收到IDalLayer作为
构造函数参数的示例。
- >
< / components>
< / castle>
< system.Web>
...
< /system.Web>
< / configuration>
这些接口和类的实现可能如下所示:
public IDalLayer
{
IRepository< T> GetRepository< T>(); //使用通用存储库的简化解决方案
Commint(); //工作单位
}
// DalLayer持有对象上下文。根据PerWebRequest的生活方式,您可以
//在请求处理过程中解决此类数次,您仍然会
//获取相同的实例=单个ObjectContext。
public class DalLayer:IDalLayer,IDisposable
{
private ObjectContext _context; //创建存储库时使用上下文
public DalLayer(string connectionString){...}
...
}
公共接口IBusinessLayer
{
//每个服务实现将从构造函数获取必要的
//存储库。
// BusinessLayer将在创建服务时传递它们
// instance
//某些业务服务公开UI层的方法
ISomeService SomeService {get; }
}
public class BusinessLayer:IBusinessLayer
{
private IDalLayer _dalLayer;
public BusinessLayer(IDalLayer dalLayer){...}
...
}
您可以为您的网页定义基类并公开业务层(您可以对可以解决的任何其他类做同样的事情):
public abstract class MyBaseForm:Page
{
private IBusinessLayer _businessLayer = null;
protected IBusinessLayer BusinessLayer
{
get
{
if(_businessLayer == null)
{
_businessLayer = IoCProvider.GetInstance()。 Container.Resolve< IBusinessLayer>();
}
return _businessLayer;
}
...
}
复杂的解决方案可能涉及使用自定义 PageHandlerFactory
来直接解析页面并注入依赖关系。如果要使用此类解决方案,请 Spring.NET 框架(另一个带IoC容器的API)。
Well, it seems like I'm stuck in my application structure. Here's what I want to do:
- UI layer: An ASP.NET webforms website.
- BLL: Business logic layer which calls the repositories on DAL.
- DAL: .EDMX file (Entity Model) and ObjectContext with Repository classes which abstract the CRUD operations for each entity.
- Entities: The POCO Entities. Persistence Ignorant. Generated by Microsoft's ADO.Net POCO Entity Generator.
I'd like to create an obejctcontext per HttpContext in my repositories to prevent performance/thread [un]safety issues. Ideally it would be something like:
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 ;
}
}
The problem is the I don't want to access HttpContext in my DAL (Where the repositories are located). But I have to somehow pass HttpContext to DAL. based on the answer to my question here, I have to use IoC pattern. Ideally I'd like to achieve something like this in amulti-layered architecture.
I've checked out Autofac and it seems very promising. But I'm not sure how could I achieve this (Passing Httpcontext to make sure one ObjectContext is instantiated per HttpContext) in a multi-layered architecture. Could anyone give me some working example on how to achieve this? How can I be aware of HttpContext in DAL without directly accessing the HttpContext in DAL? I feel like I'm a bit lost in designing a multi-layered solution.
I have never used IoC container with WebForms so get this as some high level solution which should probably be futher improved.
You can try creating some IoC provider as singleton:
public class IoCProvider
{
private static IoCProvider _instance = new IoCProvider();
private IWindsorContainer _container;
public IWindsorContainer
{
get
{
return _container;
}
}
public static IoCProvider GetInstance()
{
return _instance;
}
private IoCProvider()
{
_container = new WindsorContainer(new XmlInterpreter(new ConfigResource("castle")));
}
}
Your web.config
will have to contain sections like (the configuration is based on your previous post):
<configuration>
<configSections>
<section name="castle" type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />
</configSections>
<castle>
<components>
<component id="DalLayer"
service="MyDal.IDalLayer, MyDal"
type="MyDal.MyDalLayer, MyDal"
lifestyle="PerWebRequest">
<!--
Here we define that lifestyle of DalLayer is PerWebRequest so each
time the container resolves IDalLayer interface in the same Web request
processing, it returns same instance of DalLayer class
-->
<parameters>
<connectionString>...</connectionString>
</parameters>
</component>
<component id="BusinessLayer"
service="MyBll.IBusinessLayer, MyBll"
type="MyBll.BusinessLayer, MyBll" />
<!--
Just example where BusinessLayer receives IDalLayer as
constructor's parameter.
-->
</components>
</castle>
<system.Web>
...
</system.Web>
</configuration>
Implementation of these interfaces and classes can look like:
public IDalLayer
{
IRepository<T> GetRepository<T>(); // Simplified solution with generic repository
Commint(); // Unit of work
}
// DalLayer holds Object context. Bacause of PerWebRequest lifestyle you can
// resolve this class several time during request processing and you will still
// get same instance = single ObjectContext.
public class DalLayer : IDalLayer, IDisposable
{
private ObjectContext _context; // use context when creating repositories
public DalLayer(string connectionString) { ... }
...
}
public interface IBusinessLayer
{
// Each service implementation will receive necessary
// repositories from constructor.
// BusinessLayer will pass them when creating service
// instance
// Some business service exposing methods for UI layer
ISomeService SomeService { get; }
}
public class BusinessLayer : IBusinessLayer
{
private IDalLayer _dalLayer;
public BusinessLayer(IDalLayer dalLayer) { ... }
...
}
Than you can define base class for your pages and expose the business layer (you can do the same with any other class which can be resolved):
public abstract class MyBaseForm : Page
{
private IBusinessLayer _businessLayer = null;
protected IBusinessLayer BusinessLayer
{
get
{
if (_businessLayer == null)
{
_businessLayer = IoCProvider.GetInstance().Container.Resolve<IBusinessLayer>();
}
return _businessLayer;
}
...
}
Complex solution whould involve using custom PageHandlerFactory
to resolve pages directly and inject dependencies. If you want to use such solution check Spring.NET framework (another API with IoC container).
这篇关于具有依赖注入的实体框架ObjectContext的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!