views:

728

answers:

2

My repositories all take ISession in the constructor:

protected Repository(ISession session)
{
     this.session = session;
}
private readonly ISession session;

In an Asp.Net MVC application, using StructureMap, how would I go about setting up ISession in my the StructureMap Registry? Would I need to to add SessionFactory to the container also? Does FluentNHibernate change things?

A: 

You should register ISession using a factory method.

Another options (not always the best, but easy to use) is to:

Implement ISession and ISessionFactory interfaces (SessionProxy and SessionFactoryProxy).

public class SessionAggregator : ISession {
    protected ISession session;

    public SessionAggregator(ISessionFactory theFactory) {
        if (theFactory == null)
            throw new ArgumentNullException("theFactory", "theFactory is null.");
        Initialise(theFactory);
    }

    protected virtual void Initialise(ISessionFactory factory) {
        session = factory.OpenSession();
    }
    // the ISession implementation - proxy calls to the underlying session  
 }

public class SessionFactoryAggregator : ISessionFactory {
    protected static ISessionFactory factory;
    private static locker = new object();
    public SessionFactoryAggregator() {
            if (factory == null) {
              lock(locker) {
                if (factory == null)
                  factory = BuildFactory();
              }
            }
    }

    // Implement the ISessionFactory and proxy calls to the factory                
}

This way you can just register ISession (implemented by SessionAggregator) and ISessionFactory (SessionFactoryAggreagator) and any DI framework will resolve ISession easily.

This is good if your DI does not support factory method (I don't know if Structure Map does).

I have added these implementation to my Commons assembly so I should not reimplement it every time.

EDIT: Now, to make use of ISession in web application:

  1. Register SessionFactoryAggregator in the structure map (life time can be singleton).
  2. Register SessionAggregator in Snstrucure map and set its lifetime to InstanceScope.Hybrid.
  3. At the end of each request you need to dispose the session by calling HttpContextBuildPolicy.DisposeAndClearAll()

The code can look like:

// The Registry in StructureMap
ForRequestedType<ISessionFactory>()
        .CacheBy(InstanceScope.Singleton)
        .TheDefaultIsConcreteType<SessionFactoryAggregator>();

ForRequestedType<ISessiony>()
        .CacheBy(InstanceScope.Hybryd)
        .TheDefaultIsConcreteType<SessionAggregator>();

// Then in EndRequest call
HttpContextBuildPolicy.DisposeAndClearAll()
Dmytrii Nagirniak
I'm really looking for an StructureMap example, or using your example, how would I inject SessionAggregator and SessionFactoryAggregator into the container. Taking into consideration a web app environment, context, sessions etc.
mxmissile
I've updated the answer to show how to register that.
Dmytrii Nagirniak
That's exactly what I was looking for, thanx.
mxmissile
A: 

This question & answers might help you.

One way to go - steal nhibernate session management from "S#arp Architecture". Works great.

Arnis L.