mridula
mridula

Reputation: 3281

NHibernate LazyInitializationException when returning an Object

Can someone explain to me why is this happening - I have a one-to-many mapping between Client and Project.

Following are the two relationships in the respective mapping files:

Client:

<!-- Relationship with project -->
<bag name="projects" cascade ="all-delete-orphan" lazy="false">
  <key column="client_id" />
  <one-to-many class="Project" ></one-to-many>
</bag>

Project:

<many-to-one name="client"
         class="Client"
         column="client_id"
         cascade="all-delete-orphan" 
         fetch="join"
         not-null="false"
         lazy="false" />

Following is a web-method that returns a specific Client.

public Client RetrieveEqualsClient(string propertyName, object propertyValue)
{
    Client c = new Client();
    ConfigureNHibernate();
    using (ISession session = m_SessionFactory.OpenSession())
    {
        ICriteria criteria = session.CreateCriteria(typeof(Client));
        criteria.Add(Expression.Eq(propertyName, propertyValue));
        c = criteria.List<Client>()[0];

        return c;
    }
}

I call the method from my aspx page as follows:

$.ajax
(
    {
        type: "post",
        url: "NHibernateWebService.asmx/RetrieveEqualsClient",
        data: "{id: " + id + "}",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        error: function (result) { alert("Failure: " + result.statusText); },
        success: function (result) { alert(result); }    
     }
 )

This gives me an exception: NHibernate LazyInitializationException: failed to lazily initialize a collection, no session or session was closed, here - //this is in the Client class

public virtual IList<Project> projects 
{
    get { return c_projects ?? ( c_projects = new List<Project>()); }//Exception Occurs Here!
    set { c_projects = value; }
}

I went through various questions about this exception, but couldn't make it work.

Upvotes: 0

Views: 3180

Answers (2)

J. Ed
J. Ed

Reputation: 6752

The exception you get is caused by the fact that you're trying to load your projects collection when OUTSIDE the scope of the ISession.
This is probably happening because, when serializing, the property is read by the serializer, and it happens outside of your using scope.
The best thing to do is to use a dto instead of serializing your POCO.

So your code will look something like:

using (ISession session = m_SessionFactory.OpenSession())
    {
        ICriteria criteria = session.CreateCriteria(typeof(Client));
        criteria.Add(Expression.Eq(propertyName, propertyValue));
        var list = criteria.List<Client>();
        if (!list.Any())
           return null;
        return new ClientDTO(list[0]);
    }

Also I'm not sure about the dynamic querying you do with getting the property name from the client.
You're creating a strong coupling between your UI code and your database (if the Id property changes, that means that you have to change your jQuery code...)

If, indeed, your client always asks for a client using an Id, then the Get<Client>(id) method would be more appropriate and less error-prone.

Upvotes: 1

Alexander
Alexander

Reputation: 1319

Try to set fetch="join" for projects:

<bag name="projects" cascade ="all-delete-orphan" fetch="join"> 
  <key column="client_id" /> 
  <one-to-many class="Project" ></one-to-many> 
</bag>

Upvotes: 1

Related Questions