2

Я использую Castle Windsor для контейнера DI для Web API 2, а некоторые из моих контроллеров имеют зависимости EF DbContext, которые я впрыскиваю, используя следующие установщики CW (это часть работает отлично):Замок Windsor Lifestyle для EF DbContext, необходимый для ведения журнала после запроса веб-API

public class ApiControllerInstaller : IWindsorInstaller 
{ 
    public void Install(IWindsorContainer container, IConfigurationStore store) 
    { 
     container.Register(Classes.FromThisAssembly().BasedOn<ApiController>().LifestylePerWebRequest()); 
    } 
} 

public class MyEntitiesInstaller : IWindsorInstaller 
{ 
    public void Install(IWindsorContainer container, IConfigurationStore store) 
    { 
     container.Register(Component.For<MyEntities>().LifestylePerWebRequest()); 
    } 
} 

у меня также есть глобальное протоколирование на месте с помощью следующего обработчика сообщений:

public class LoggingHandler : DelegatingHandler 
{ 
    private readonly IWindsorContainer _container; 

    public LoggingHandler(IWindsorContainer container) 
    { 
     _container = container; 
    } 

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, 
                   CancellationToken cancellationToken) 
    { 
     // Logic here to parse the request, send off the request, and then parse the response for logging info 

     // Log to database 
     using (MyEntities myEntities = _container.Resolve<MyEntities>()) 
     { 
      // Log to database using MyEntities (DbContext) 
     } 

     return response; 
    } 
} 

... который получает набор в WebApiConfig.cs, как это:

public static void Register(HttpConfiguration config, IWindsorContainer container) 
    { 
     // Unrelated code 

     config.MessageHandlers.Add(new LoggingHandler(container)); 
    } 

Проблема заключается в том, что я получаю исключение в LoggingHandler при попытке доступа к MyEntities (который расширяет EF DbContext), поскольку он говорит, что он уже был удален. Я думаю, что это происходит потому, что MyEntitiesInstaller регистрирует его как LifestylePerWebRequest(), и к этому моменту запрос уже завершен. Я не думаю, что это хорошая идея в глобальном изменении образа жизни DbContext, потому что для целей контроллера api мы хотим, чтобы он был экземпляром для каждого веб-запроса. Но как я могу предотвратить его удаление до начала регистрации (или, что еще лучше, использовать отдельный экземпляр для ведения журнала)?

+0

Я никогда не использовал Castle Windsor, но разве он не поддерживает «названные» конфигурации вещей? Моим инстинктом было бы создать альтернативную именованную конфигурацию для DbContext, а затем настроить свой атрибут для ее использования. – Casey

+0

Я не уверен, что регистрация «MyEntities» - это умная идея. Они должны быть недолговечными в течение всего срока службы запроса, а не всего веб-запроса. Я бы сохранил это просто и просто использовал 'using (var entityContext = new MyEntities())' вместо этого. Нет необходимости в [* «Ввести все вещи» *] (http://s.quickmeme.com/img/fe/fe05577986250c85a9df4c46dbf46afb33332155da3e0f590cfd99bf5259b1dd.jpg). –

+0

@emodendroket Спасибо! Похоже, что именованные экземпляры - это то, что мне нужно - я новичок в контейнерах DI и не знал об этой функции. Я попытаюсь посмотреть, будет ли работать отдельный именованный экземпляр. – mayabelle

ответ

2

Спасибо за комментарий @ emodendroket за указание на меня в правильном направлении. Я смог получить эту работу, используя другой именованный экземпляр для DbContext, который мне нужен за пределами веб-запроса, используя переходный образ жизни (и ручную утилизацию сразу после использования).

Installer:

public class MyEntitiesInstaller : IWindsorInstaller 
{ 
    public void Install(IWindsorContainer container, IConfigurationStore store) 
    { 
     container.Register(Component.For<MyEntities>().LifestylePerWebRequest().IsDefault(), 
          Component.For<MyEntities>().Named("MyEntitiesTransient").LifestyleTransient()); 
    } 
} 

Использование лесозаготовительного обработчика:

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, 
                  CancellationToken cancellationToken) 
{ 
    // Logic here to parse the request, send off the request, and then parse the response for logging info 

    // Log to database 
    using (MyEntities myEntities = _container.Resolve<MyEntities>("MyEntitiesTransient")) 
    { 
     // Log to database using MyEntities (DbContext) 

     _container.Release(myEntities); 
    } 

    return response; 
} 

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

 Смежные вопросы

  • Нет связанных вопросов^_^