实体框架ObjectContext的使用依赖注入 [英] Entity Framework ObjectContext with Dependency Injection

查看:125
本文介绍了实体框架ObjectContext的使用依赖注入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

唉,好像我被困在我的应用程序结构。这是我想做的事:


  • 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的?我觉得我有点在设计一个多层次的解决方案丢失。


解决方案

我从来没有使用与W​​ebForms的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:IBus​​inessLayer
{
  私人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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆