Reputation: 3281
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
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
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