views:

1422

answers:

2

I am writing a web app using Castle ActiveRecord, and I keep getting this exception whenever I try to access a lazy loaded list of related objects. Here is my code:

        using(new SessionScope())
        {
            foreach (var field in eventObj.RegistrationFields)
            {
                //Do something with the field here...
            }
        }

The RegistrationFields property looks like this:

    [HasMany(Inverse = true, Lazy = true)]
    public IList<EventRegistrationField> RegistrationFields { get; set; }

The exception happens when the "eventObj.RegistrationFields" is accessed for the foreach loop. I also made sure to set the isweb="true" attribute in my activeRecord config settings. Does anyone know why this would happen? Here is my config:

<connectionStrings>
  <add name="main" connectionString="Data Source=localhost\SQLEXPRESS;Initial Catalog=EventScheduler;Integrated Security=SSPI"/>
</connectionStrings>
<activerecord isWeb="true">
  <config>
    <add key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver"/>
    <add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2005Dialect"/>
    <add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider"/>
    <add key="hibernate.connection.connection_string_name" value="main"/>
  </config>
</activerecord>
+1  A: 

When was eventObj loaded? That needs to be in the session too. Also, check out the ActiveRecord integration section of the docs:

+5  A: 

I think you're getting confused about sessions. RegistrationFields is a lazy property of eventObj. It is the session that loaded eventObj that would be responsible for loading RegistrationFields. You're explicitly opening a new session by using new SessionScope(), which creates a new session to which eventObj is not bound; therefore there is no owning session for it to get the data from. Even if the originating session is still alive, calling new SessionScope() nests a new session and hides the old one where it can't be seen until Dispose() is called on the current scope. Objects will not automatically attach themselves to the current session. This is the expected NHibernate behaviour.

It looks like you're trying to do session-per-unit-of-work, which is fine, but then the loading of objects and the resolution of all those objects' lazy collections must happen within that unit of work.

You could try moving to session-per-request (see the Castle docs for how to make this happen) and dropping the SessionScope creation. This will keep your objects live for the duration of a page request (which is as far as any lazy collection should live in a Web app). You must be aware, though, that in this scenario any change you make to a persistent object will be written to the DB on session flush (in effect, you should treat a change to the state of a persistent object as a change to the underlying data as if they were the same operation - then you can't go wrong).

DotNetGuy