Доступ к HttpContext.Current на уровне доступа к данным - PullRequest
0 голосов
/ 06 января 2011

Основываясь на данном ответе на мой вопрос в Entity Framework в многоуровневой архитектуре , теперь я бы хотел переместить свои репозитории (которые теперь отвечают только за абстракцию CRUD, а не за бизнес-логику) в DALи зарезервировать BLL для Business Logic.
Я пришел к выводу, что контекст сущности должен рассматриваться как единица работы и, следовательно, не использоваться повторно.Поэтому я хотел бы создать 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 ;
        }
    }

В этом случае проект DAL должен знать о переменной HttpContext.Current.Я не уверен, что это хорошая практика, и хотел бы узнать ваше мнение.

1 Ответ

2 голосов
/ 06 января 2011

Отсутствие доступа к HttpContext вне веб-приложения - плохая практика, поскольку оно тесно связывает ваш код с веб-средой. Вероятно, вам нужно инвертировать контейнер управления с помощью менеджера времени жизни объекта 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 строить весь объект.

Для инверсии контрольных контейнеров проверьте, например, Виндзорский замок . Я использую MS Unity, но он не предоставляет встроенный менеджер времени жизни HTTP из коробки.

...