3

I'm new to the whole castle Windsor, Nhibernate, Fluent and Automapping stack so excuse my ignorance here. I didn't want to post another question on this as it seems there are already a huge number of questions that try to get a solution the Windsor nhib Isession management problem, but none of them have solved my problem so far. I am still getting a ISession is closed exception when I'm trying to call to the Db from my Repositories,Here is my container setup code.

container.AddFacility<FactorySupportFacility>()
            .Register(
                Component.For<ISessionFactory>()
                    .LifeStyle.Singleton
                    .UsingFactoryMethod(() => Fluently.Configure()
                                                  .Database(
                                                      MsSqlConfiguration.MsSql2005.
                                                          ConnectionString(
                                                              c => c.Database("DbSchema").Server("Server").Username("UserName").Password("password")))
                                                  .Mappings
                                                     (
                                                      m => 
                                                      m.AutoMappings.Add
                                                        (
                                                          AutoMap.AssemblyOf<Message>(cfg)
                                                          .Override<Client>(map =>
                                                          {
                                                              map.HasManyToMany(x => x.SICCodes).Table("SICRefDataToClient");
                                                          })
                                                          .IgnoreBase<BaseEntity>()
                                                          .Conventions.Add(DefaultCascade.SaveUpdate())
                                                          .Conventions.Add(new StringColumnLengthConvention(),new EnumConvention())
                                                          .Conventions.Add(new EnumConvention())

                                                          .Conventions.Add(DefaultLazy.Never())
                                                        )
                                                      )
                                                  .ExposeConfiguration(ConfigureValidator)
                                                  .ExposeConfiguration(BuildDatabase)
                                                  .BuildSessionFactory() as SessionFactoryImpl),
                 Component.For<ISession>().LifeStyle.PerWebRequest.UsingFactoryMethod(kernel => kernel.Resolve<ISessionFactory>().OpenSession()
                                                  ));

In my repositories i inject private readonly ISession session; and use it as followes

 public User GetUser(int id)
    {
        User u;

            u = session.Get<User>(id);
            if (u != null && u.Id > 0)
            { 
                NHibernateUtil.Initialize(u.UserDocuments);
            }


        return u;

in my web.config inside <httpModules>. i have also added this line

      <add name="PerRequestLifestyle" 
type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor"/>

I'm i still missing part of the puzzle here, i can't believe that this is such a complex thing to configure for a basic need of any web application development with nHibernate and castle Windsor.

I have been trying to follow the code here windsor-nhibernate-isession-mvc and i posted my question there as they seemed to have the exact same issue but mine is not resolved.

UPDATE MooKid8000 i have now updated my castle register code to this

private void AddRepositories()
    {
        container.Register(
            AllTypes.FromAssembly(typeof(MembershipRepository).Assembly)
                .Pick()
                .Configure(c => c.Interceptors(
                    InterceptorReference.ForKey("simpleLogger")).Anywhere
                )
                .Configure(c => c.LifeStyle.Is(LifestyleType.Transient))
                .WithService.FirstInterface());
    }

But I'm still getting the ISession is closed issue, Do my services need to be registered as Transient as well, Can you explain in more detail why they should be transient and not singleton's

UPDATE MooKid8000 suggestion was 100% correct , I just need to make sure my services and repositories where all scoped as LifestyleType.Transient so the ISession wasn't wiped out. Great spot Mookid8000 without even seeing my castle registration code initially.

For anybody that is intrested contact me and i can send you my container setup.

Community
  • 1
  • 1
Simon
  • 415
  • 1
  • 4
  • 15
  • 1
    You may be interested in going through Windsor tutorial which uses ASP.NET MVC and NHibernate and is targeted at people with no prior experience with Windsor or IoC concepts. http://stw.castleproject.org/Windsor.Windsor-tutorial-ASP-NET-MVC-3-application-To-be-Seen.ashx Don't forget to share your feedback about the tutorial if anything is not clear, something is confusing, or not explained well enough – Krzysztof Kozmic Dec 29 '10 at 23:31
  • Fluent syntax at it's worst. I'm not even going to attempt to read what that codes trying to do. Sorry. – Phill Dec 30 '10 at 12:48
  • I will check this out in detail later where was this when i was searchiing for hours on end the last few weeks for a such an asp.net mvc 3 example – Simon Dec 30 '10 at 12:49
  • Phil yes it hard to follow whats going on, i was following on from help i received setting up the project this way, the fluent hibernate code works well albeit its dirty looking, the issue is that my ISession is not getting created per request and injected into the repository, it's always closed – Simon Dec 30 '10 at 12:52

1 Answers1

5

Did you remember to register your repositories with a transient lifestyle?

If your repositories are singletons (which is the default lifestyle with Windsor), then the injected ISession instance will be "caught", resulting in closed session errors later on.

Note that any services using your repositories must also have a transient lifestyle, as well as any services using those services, and so on.

Generally, you could say that the lifestyle granularity should not increase as you go further away from the composition root, otherwise some kind of scoping will happen. Of course this is not always a problem, but it can lead to errors that are pretty hard to diagnose.

mookid8000
  • 18,258
  • 2
  • 39
  • 63
  • I've updated my main question so i could add some more code, but i'm still getting the ISession is closed when I try to hit the DB – Simon Dec 30 '10 at 12:47
  • Ok - but how about any services dependant on your repositories? My suspicion is that the per-request scoped `ISession` is accidentally scoped to singleton, which usually results in the error you're experiencing. – mookid8000 Dec 30 '10 at 13:19
  • 1
    mookid that's it fixed I scoped all my services as LifestyleType.Transient now and the ISession is alive when I'm hitting the repositories, I can now turn lazy loading back on ;-), thanks so much i knew it had to be something simple but when you're new to everything your using its very difficult to spot. I really need to do more reading on castle, many many thanks for this, i have literally tearing my hair out over this for 3 weeks now. – Simon Dec 30 '10 at 13:56