WCF / S # arpArch: базовая ISession закрывается после первого вызова в запросе - PullRequest
2 голосов
/ 04 марта 2010

Я знаю, что использование WCF в SA устарело, потому что оно перейдет в SA Contrib. Но до тех пор, пока это не произойдет, я думаю, что я должен использовать поддержку в SA.

Тем не менее у меня проблема с закрытием основного сеанса NHibernate после вызова службы WCF. DbContext.Session моего репозитория закрывается после первого вызова, поэтому я не могу вызвать свою службу более одного раза за один HTTP-запрос.

Я настроил WCF в своем проекте на основе примера приложения Northwind. Образец вызывает службу WCF только один раз за запрос, поэтому эта проблема там не отображается. Проблема легко воспроизводится, если дублировать следующую строку в TerritoriesController:

территорий = территорийWcfService.GetTerritories ();

Это вызывает исключение ObjectDisposedException: "Сеанс закрыт! Объект имя: 'ISession' ".

Есть идеи?

Ответы [ 2 ]

3 голосов
/ 04 марта 2010

Мне удалось ее решить.

Изучив исходный код SharpArch.Wcf, я обнаружил, что перед отправкой ответа службы WCF он всегда закрывает все сеансы NHibernate. Это само по себе хорошо.

Кроме того, я обнаружил, что мои клиентские прокси-фабрики запускались только один раз за веб-запрос, а второй вызов службы должен вызывать новый экземпляр прокси. В результате второй вызов службы завершился ошибкой, поскольку основной сеанс NHibernate уже был закрыт. Я решил это, украсив прокси-классы своего клиента с помощью Castle.Core.TransientAttribute , который оставляет управление временем жизни до фабрики, которая создает клиента. В результате наши прокси-фабрики вызываются каждый раз, когда запрашивается прокси.

Во-вторых, мне пришлось зарегистрировать прокси-серверы следующим образом (в классе ComponentRegistrar ):

container.AddFacility("WcfSessionFacility", new WcfSessionFacility());

container.Kernel.AddComponentWithExtendedProperties(
    "AccountService",
    typeof(IAccountService),
    typeof(AccountServiceClient),
    new Dictionary<string, object>()
        {
            { WcfSessionFacility.ManageWcfSessionsKey, true }
        });

WcfSessionFacility управляет закрытием / прерыванием клиента в зависимости от его состояния. Это гарантирует, что клиентский канал будет закрыт всякий раз, когда клиентский прокси уничтожен, поэтому нам не нужно помещать наши вызовы в блоки try-catch.

Как и я, вы могли бы подумать о настройке управления временем жизни при добавлении компонента вместо использования атрибута, но, очевидно, нет подходящей перегрузки AddComponentWithExtendedProperties , которая позволяет это.

1 голос
/ 04 марта 2010

Я не очень знаком с SharpArchitecture, но, похоже, у вас есть как минимум два варианта:

  1. На стороне клиента утилизируйте службу WCF после первый звонок и новый еще один WCF Служба перед вторым вызов, таким образом получая новую ISession.

  2. Сделайте сервис WCF умнее об утилизации сессии, так что вы может держать сеанс открытым дольше. Есть несколько способов сделать это и это, вероятно, предполагает приличный количество новой логики в сервисе WCF, но оно должно быть полностью осуществимым.

...