Как я могу внедрить несколько репозиториев в обработчик сообщений NServicebus?

Я использую следующее:

public interface IRepository<T>
{
   void Add(T entity);
}

public class Repository<T>
{
  private readonly ISession session;

  public Repository(ISession session)
  {
    this.session = session;
  }

  public void Add(T entity)
  {
     session.Save(entity);
  }
}

public class SomeHandler : IHandleMessages<SomeMessage>
{
  private readonly IRepository<EntityA> aRepository;
  private readonly IRepository<EntityB> bRepository;

  public SomeHandler(IRepository<EntityA> aRepository, IRepository<EntityB> bRepository)
  {
    this.aRepository = aRepository;
    this.bRepository = bRepository; 
  }

  public void Handle(SomeMessage message)
  {
   aRepository.Add(new A(message.Property);
   bRepository.Add(new B(message.Property);
  }
}

public class MessageEndPoint : IConfigureThisEndpoint, AsA_Server, IWantCustomInitialization
{
   public void Init()
   {
      ObjectFactory.Configure(config =>
        {
            config.For<ISession>()
                .CacheBy(InstanceScope.ThreadLocal)
                .TheDefault.Is.ConstructedBy(ctx => ctx.GetInstance<ISessionFactory>().OpenSession());
            config.ForRequestedType(typeof(IRepository<>))
                .TheDefaultIsConcreteType(typeof(Repository<>));
   }
}

Моя проблема с локальным хранилищем потоков заключается в том, что один и тот же сеанс используется во время всего потока приложения. Я обнаружил это, когда увидел, что кеш первого уровня не очищен. Я хочу использовать новый экземпляр сеанса перед каждым вызовом IHandleMessages‹>.Handle. Как я могу сделать это со структурной картой? Должен ли я создавать модуль сообщений?


person Paco    schedule 24.03.2010    source источник
comment
Используете ли вы модуль сообщений для обработки открытия сеанса?   -  person Andreas Öhlund    schedule 24.03.2010
comment
В настоящее время нет, я просто использую карту структуры для разрешения сеанса. Должен ли я?   -  person Paco    schedule 24.03.2010
comment
Вы правы в том, что один и тот же сеанс используется для всех запросов к одному и тому же потоку. Это связано с тем, что NSB не создает новые потоки для каждого запроса. У меня сейчас нет обходного пути, нужно еще немного подумать над этим.   -  person Andreas Öhlund    schedule 24.03.2010
comment
Обойти тот факт, что NSB повторно использует нить, будет сложно. Чтобы очистить кеш, вы можете реализовать модуль сообщений, который очищает сеанс... public class SessionClearModule:IMessageModule { private IContainer container; public SessionClearModule (контейнер IContainer) { this.container = container; } public void HandleBeginMessage() { container.GetInstance‹ISession›().Clear(); } public void HandleEndMessage() { } public void HandleError() { } }   -  person Andreas Öhlund    schedule 24.03.2010
comment
Я думал об этом, но боюсь, что сеанс может держать соединение открытым. Неважно, если это один раз, но я хочу иметь возможность использовать обработчик сообщений в нескольких потоках на нескольких машинах, взаимодействующих с одной базой данных, поэтому я ищу решение, которое действительно создает новый сеанс каждый раз.   -  person Paco    schedule 24.03.2010
comment
Я думаю, это может быть достигнуто путем реализации пользовательского режима кеша для StructureMap, который предоставляет доступ к кешу и тем самым позволяет нам очищать его с помощью модуля сообщений. Я вернусь к вам об этом!   -  person Andreas Öhlund    schedule 25.03.2010


Ответы (1)


Вы правы в том, что один и тот же сеанс используется для всех запросов к одному и тому же потоку. Это связано с тем, что NSB не создает новые потоки для каждого запроса. Обходной путь заключается в добавлении пользовательского режима кэширования и его очистке после завершения обработки сообщения.

1. Расширьте жизненный цикл хранилища потоков и подключите его к модулю сообщений.

public class NServiceBusThreadLocalStorageLifestyle : ThreadLocalStorageLifecycle, IMessageModule
{

    public void HandleBeginMessage(){}

    public void HandleEndMessage()
    {
        EjectAll();
    }

    public void HandleError(){}
}

2. Настройте карту структуры следующим образом:

For<<ISession>>
.LifecycleIs(new NServiceBusThreadLocalStorageLifestyle())
...

Надеюсь это поможет!

person Andreas Öhlund    schedule 25.03.2010
comment
Рад слышать! Я собираюсь включить пользовательский жизненный цикл в наш конструктор объектов StructureMap, как только смогу. - person Andreas Öhlund; 25.03.2010
comment
Основная версия конструктора StructureMap теперь включает указанный выше жизненный цикл. - person Andreas Öhlund; 02.04.2010