实体框架ObjectContext的使用依赖注入 [英] Entity Framework ObjectContext with Dependency Injection
问题描述
唉,好像我被困在我的应用程序结构。这是我想做的事:
- UI层:一个ASP.NET WebForms的网站
- BLL:业务逻辑层,它调用DAL的库
- DAL:.edmx文件(实体模型),并与ObjectContext的类库抽象而CRUD操作为每个实体
- 实体:POCO实体。持久性无知。微软的ADO.Net POCO实体发生器产生。
我想在我的资料库,以prevent性能/线程(联合国)的安全问题,以每创建一个HttpContext的obejctcontext。理想情况下是这样的:
公共MyDBEntities CTX
{
得到
{
字符串ocKey =ctx_+ HttpContext.Current.GetHash code()的ToString(X)。
如果(!HttpContext.Current.Items.Contains(ocKey))
HttpContext.Current.Items.Add(ocKey,新MyDBEntities());
返回HttpContext.Current.Items [ocKey]作为MyDBEntities;
}
}
问题是我不想要访问的HttpContext在我的DAL(凡库的位置)。但是,我必须以某种方式传递的HttpContext DAL。基于答案在这里我的问题 ,我必须使用IoC模式。理想情况下,我想实现的东西像这在市值数分层架构。
我已经签出Autofac,似乎非常有前途的。的但的我不知道我怎么能做到这一点(传递的HttpContext请确定已ObjectContext的每HttpContext的实例化)的多层体系结构。任何人都可以给我如何实现这一目标的一些工作的例子吗?我怎么能知道的HttpContext在DAL不必直接访问在DAL HttpContext的?我觉得我有点在设计一个多层次的解决方案丢失。
解决方案
我从来没有使用与WebForms的IoC容器,以便得到这个作为可能应该进一步的提高一些高层次的解决方案
您可以尝试创建一些国际奥委会提供商为单:
公共类IoCProvider
{
私有静态IoCProvider _instance =新IoCProvider(); 私人IWindsorContainer _container; 公共IWindsorContainer
{
得到
{
返回_container;
}
} 公共静态IoCProvider的GetInstance()
{
返回_instance;
} 私人IoCProvider()
{
_container =新WindsorContainer(新XmlInter preTER(新ConfigResource(城堡)));
}
}
您的web.config
必须包含类似的部分(该配置是基于你的<一个href=\"http://stackoverflow.com/questions/4612681/accessing-httpcontext-current-in-data-access-layer\">$p$pvious帖子):
&LT;结构&gt;
&LT; configSections&GT;
&lt;节名称=城堡式=Castle.Windsor.Configuration.AppDomain.CastleSectionHandler,Castle.Windsor/&GT;
&LT; / configSections&GT; &LT;&城堡GT;
&LT;成分&gt;
&lt;成分ID =DalLayer
服务=MyDal.IDalLayer,MyDal
类型=MyDal.MyDalLayer,MyDal
生活方式=PerWebRequest&GT;
&LT;! -
在这里,我们定义DalLayer的生活方式是PerWebRequest所以每个
时间容器解决IDalLayer接口在同一Web请求
处理后,返回DalLayer类的同一个实例
- &GT;
&LT;&参数GT;
&LT;&的connectionString GT; ...&LT; /&的connectionString GT;
&LT; /参数&GT;
&LT; /成分&gt;
&lt;成分ID =BusinessLayer
服务=MyBll.IBusinessLayer,MyBll
键入=MyBll.BusinessLayer,MyBll/&GT;
&LT;! -
其中,BusinessLayer接收IDalLayer刚才的例子
构造函数的参数。
- &GT;
&LT; /成分&gt;
&LT; /城堡&GT; &LT;&的System.Web GT;
...
&LT; /system.Web>
&LT; /结构&gt;
这些接口和类的实施可以如下:
公共IDalLayer
{
IRepository&LT; T&GT; GetRepository&LT; T&GT;(); //使用通用的存储库简化的解决方案
Commint(); //工作单位
}// DalLayer持有对象上下文。 PerWebRequest的生活方式,你可以的Bacause
//解析请求处理过程中该类几个时间,你仍然会
//得到相同的实例=单ObjectContext的。
公共类DalLayer:IDalLayer,IDisposable接口
{
私人ObjectContext的_context; //创建库时使用上下文 公共DalLayer(字符串的connectionString){...} ...
}公共接口IBusinessLayer
{
//每个服务实现将接受必要的
//从构造函数库。
//创建服务时BusinessLayer将通过他们
//实例 //一些业务服务暴露了UI层的方法
ISomeService SomeService {搞定; }
}公共类BusinessLayer:IBusinessLayer
{
私人IDalLayer _dalLayer; 公共BusinessLayer(IDalLayer dalLayer){...} ...
}
比你可以定义基类为您的网页,并暴露业务层(你可以做同样的与其他任何类,它可以解决):
公共抽象类MyBaseForm:页
{
私人IBusinessLayer _businessLayer = NULL;
保护IBusinessLayer BusinessLayer
{
得到
{
如果(_businessLayer == NULL)
{
。_businessLayer = IoCProvider.GetInstance()Container.Resolve&LT; IBusinessLayer&GT;();
} 返回_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屋!