Entity Framework ObjectContext с внедрением зависимостей - PullRequest
0 голосов
/ 06 января 2011

Ну, похоже, я застрял в моей структуре приложения. Вот что я хочу сделать:

  • Уровень пользовательского интерфейса: веб-сайт ASP.NET.
  • BLL: слой бизнес-логики, который вызывает репозитории в DAL.
  • DAL: файл .EDMX (Entity Model) и ObjectContext с классами репозитория, которые абстрагируют операции CRUD для каждой сущности.
  • Сущности: сущности POCO. Упорство Ignorant. Сгенерировано Microsoft ADO.Net POCO Entity Generator.

Я бы хотел создать obejctcontext для каждого HttpContext в моих репозиториях, чтобы предотвратить проблемы с производительностью / потоком [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 ());
        return HttpContext.Current.Items[ocKey] as MyDBEntities ;
    }
}  

Проблема в том, что я не хочу получать доступ к HttpContext в моем DAL (где расположены репозитории). Но я должен как-то передать HttpContext в DAL. исходя из ответа на мой вопрос здесь , я должен использовать шаблон IoC. В идеале я хотел бы достичь чего-то вроде this в многослойной архитектуре.

Я проверил Autofac, и это кажется очень многообещающим. Но Я не уверен, как мне достичь этого (передача Httpcontext, чтобы убедиться, что один ObjectContext создается для HttpContext) в многоуровневой архитектуре. Может ли кто-нибудь дать мне рабочий пример того, как этого добиться? Как я могу знать о HttpContext в DAL без прямого доступа к HttpContext в DAL? Я чувствую себя немного потерянным при разработке многослойного решения.

1 Ответ

3 голосов
/ 07 января 2011

Я никогда не использовал IoC-контейнер с WebForms, поэтому воспринимайте это как высокоуровневое решение, которое, вероятно, должно быть улучшено.

Вы можете попробовать создать провайдера IoC как синглтон:

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")));
  }
}

Ваш web.config должен будет содержать такие разделы, как (конфигурация основана на вашем предыдущем посте ):

<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>

Реализация этих интерфейсов и классов может выглядеть следующим образом:

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) { ... }

  ...
}

Чем вы можете определить базовый класс для своих страниц и представить бизнес-уровень (вы можете сделать то же самое)с любым другим классом, который может быть разрешен):

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 framework (еще один API с контейнером IoC).

...