views:

229

answers:

1

I use the following:

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

My problem with the threadlocal storage is, is that the same session is used during the whole application thread. I discovered this when I saw the first level cache wasn't cleared. What I want is using a new session instance, before each call to IHandleMessages<>.Handle. How can I do this with structuremap? Do I have to create a message module?

+2  A: 

You're right in that the same session is used for all requests to the same thread. This is because NSB doesn't create new threads for each request. The workaround is to add a custom cache mode and have it cleared when message handling is complete.

  1. Extend the thread storage lifecycle and hook it up a a message module

public class NServiceBusThreadLocalStorageLifestyle : ThreadLocalStorageLifecycle, IMessageModule
{

  public void HandleBeginMessage(){}

    public void HandleEndMessage()
    {
        EjectAll();
    }

    public void HandleError(){}
}

2.Configure your structuremap as follows:

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

Hope this helps!

Andreas
Thanks for your help! This works.
Paco
Nice to hear! I'm going to include the custom lifecycle in our StructureMap object builder as soon as I can.
Andreas
The trunk version of the StructureMap builder now includes the above lifecycle
Andreas