Grandchild lazy load problem - failed to lazily initialize a collection of role no session or session was closed

2,087 views
Skip to first unread message

Gregory Kaidanov

unread,
Jan 24, 2010, 11:27:28 AM1/24/10
to Fluent NHibernate, ste...@rnbsolutions.net, tzvi.k...@ness.com
Hi!
I've came across this problem , and no idea how to resolve the
situation.

I have a model such as:

entity1
hasmany(entity2)

entity2
hasmany(entity3)


at my test I am trying to get entity3 through entity1
and getting this message .
does anyone have some clue how to resolve it ?

my entities looks like this :

public class Entity1 : Entity
{
#region "Relationships"
private ICollection< Entity2> _col_ Entity2 = new HashSet<
Entity2 >();

public virtual ICollection< Entity2 > Col_ Entity2
{
get { return _col_ Entity2 ; }
protected set { _col_ Entity2 = value; }
}
#endregion
}


public class Entity2 : Entity
{
#region "Relationships"
private ICollection< Entity3> _col_ Entity3 = new HashSet<
Entity3 >();

public virtual ICollection< Entity3 > Col_ Entity3
{
get { return _col_ Entity3 ; }
protected set { _col_ Entity3 = value; }
}
#endregion
}

at the mapping :

public class Entity1 Mapping : ClassMap< Entity1 >
{
public Entity1Mapping()
{
try
{
LazyLoad();
Table("tableSource");

Id(x => x.ID).Length(10).Column("RECID");
Map(x => x.Col1).Column("COLUMN1");
HasMany<Entity2>(x => x.Col_ Entity2).AsBag()
.KeyColumn("COLUMN_OF_CHILD_TO_JOINBY")
.PropertyRef("Col1");

}
catch (NHibernate.HibernateException ex)
{
throw new Exception
(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType + "." +
System.Reflection.MethodBase.GetCurrentMethod().Name, ex);
}
}
}


----------------------

public class Entity2 Mapping : ClassMap < Entity2 >
{

//public virtual int Shm_medinaid { get; set; }
//public virtual int Shm_sherutid { get; set; }

public Entity2Mapping()
{
try
{
LazyLoad();

Table("tableSource2");

Id(x => x.ID).Length(10).Column("RECID");


Map(x => x.Col1).Column("COL1");
Map(x => x.Col2).Column("COL2");

HasMany<Entity3>(x => x.Col_Entity3).AsBag()
.KeyColumn("COLUMN_OF_CHILD_TO_JOINBY")
.PropertyRef("Col2");
}
catch (NHibernate.HibernateException ex)
{
throw new Exception
(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType + "." +
System.Reflection.MethodBase.GetCurrentMethod().Name, ex);
}

}

}
--------------------------------------


So at my test I am trying to reach the Entity3

[Test]
public void TestMapping()
{
Entity1 _entity1;

using (ISession Session =
NHibernateSessionProvider.GetSession())
{
long RECID = 847;

using (NHibernate.ITransaction Tran =
Session.BeginTransaction())
{
_entity1 = Session.Get< Entity1>(TMD_RECID);

Assert.AreNotEqual(_entity1.Col_Entity2, null);
IList<Entity2> _entity2 = new List<Entity2>
(_entity1.Col_Entity2);

IList<Entity3> _entity3 = new List<Entity3>
(_entity2[0].Col_Entity3);

Assert.AreNotEqual(_entity3[0].Col1, 0);


Tran.Commit();
}
}
}
-----------------------


I am failing at IList<Entity3> _entity3 = new List<Entity3>(_entity2
[0].Col_Entity3);

Initializing[Entity2#1]-failed to lazily initialize a collection of
role: Entity2.Col_Entity3, no session or session was closed
NHibernate.LazyInitializationException: Initializing[Entity2#1]-
failed to lazily initialize a collection of role:
Entity2.Col_Entity3, no session or session was closed
at
NHibernate.Collection.AbstractPersistentCollection.ThrowLazyInitializationException
(String message)

will appreciate any input on the subject .

Hudson Akridge

unread,
Jan 24, 2010, 11:47:03 AM1/24/10
to fluent-n...@googlegroups.com
Going to try taking a stab at this.

First, what's probably a better idea for you to lazy load, is the collections themselves instead of putting a lazy load on the entities and expecting everything to lazy load the entity. Fortunately LazyLoad is the default for collections in NHibernate so it's being implicitly set. So, to rule out possible conflicting variables, I'd recommend first removing the LazyLoad() calls from your mappings.

Second, there's no need to put your mapping blocks in a try/catch. I don't believe that will give you an NHibernate exception, because when the ClassMap mappings are executed, you're in FNH territory, and you'd only get an exception if there was an issue with how you've configured a FNH mapping. It then takes those, and creates an NHibernate mapping file as a result, then loads that in the config. You'd be better off putting the try/catch on your configuration class when you call .Configure().

Third, to get to the root of the issue. How you're getting to entity3 does not seem correct to me. You should be loading entity1, then going through entity 1's collection of entity2's to get an entity2, then go through entity2's collection of entity3's to get an entity3. What you're doing is putting each new entity in a new collection and then expecting the class lazy load to handle lazy loading the sub-collection. To simplify, do not put the entities in a new list. Do something like:

_entity2 =_entity.Col_Entity2.First();
_entity3 = _entity2.Col_Entity3.First();

By copying the collection of entity2's into a new list (and entity3), you're getting around the proxy class of your entities that NHibernate created for you. Those proxies are important, because they handle how to lazy load entities through collections. Otherwise, your session probably won't know how to go out and get the entity it's attempting to load. You're basically circumventing the proxy responsible for lazyloading, and then wondering why you're getting an error lazy loading ;) .

It also seems, based on your other posts, that you're having issues with propertyref with multiple columns. That is true, propertyref will only work with one column (as far as I know with current version NH). If you're in a legacy database, you might want to look at mapping each of your classes with CompositeId().AddPropertyKey(x=> x.Col1).AddPropertyKey(x=>x.Col2), instead of mapping the recid. If the RecId is not actually ever used for a relationship anywhere, then it's not what NHibernate would term an Id. CompositeId map your Col1 and Col2, then you don't need to do a propertyref everywhere. That might help resolve your other issues.


--
You received this message because you are subscribed to the Google Groups "Fluent NHibernate" group.
To post to this group, send email to fluent-n...@googlegroups.com.
To unsubscribe from this group, send email to fluent-nhibern...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/fluent-nhibernate?hl=en.




--
- Hudson
http://www.bestguesstheory.com
http://twitter.com/HudsonAkridge

Gregory Kaidanov

unread,
Jan 25, 2010, 2:40:22 AM1/25/10
to Fluent NHibernate
Thanks for the response.

1). Removed LazyLoad from general mapping and mapped only the
relationships as LazyLoad.
2).Removed the try- catch from the mapping, and left only try-catch in
configuration file
3).The previous test looked like this :
_productRetrieval = Session.Get<Entity1>(TMD_RECID);

Assert.AreNotEqual(_productRetrieval.Col_Entity2,
null);
IEnumerator<Entity2> _entity2List = _entity1.Col_
Entity2.GetEnumerator();
_Entity2List.MoveNext();
IEnumerator<Entity3> _entity3List =
_entity2List.Current.Col_Entity3.GetEnumerator();
_entity3List.MoveNext();
Assert.AreNotEqual(_entity3List.Current.Col2, 0);

And still I've got the mistake of initializing lazyload.
4).I"ll check the option of
CompositeId().AddPropertyKey(x=> x.Col1).AddPropertyKey(x=>x.Col2)
And get back to you on that.
If you have some example that shows joining by 2 column other than ID
that will help us a lot .

> > fluent-nhibern...@googlegroups.com<fluent-nhibernate%2Bunsubscr i...@googlegroups.com>

Gregory Kaidanov

unread,
Jan 25, 2010, 3:02:23 AM1/25/10
to Fluent NHibernate
the only ugly solution we've thought about
in the test to enter the line

Session.Refresh(_entity3List.Current);

than it seems to open the proxies , refresh the object and to get the
data.
it seems the wrong approach . doesn't feel wright.

Gregory Kaidanov

unread,
Jan 25, 2010, 3:15:33 AM1/25/10
to Fluent NHibernate
CompositeID -
1).Doesn't seem to handle collections.
2).Doesn't have AddPropertyKey(x=>x.Col2) - it has KeyProperty .
3).We want to have HasManyToMany relationships .
Thanks for your reply nevertheless.
Maybe I don't get something.
Can you supply some sample ?

> ...
>
> read more »

Hudson Akridge

unread,
Jan 25, 2010, 9:07:25 AM1/25/10
to fluent-n...@googlegroups.com
re: LazyLoading:
That's very strange. Even given the possibility of your mappings needing to be worked on a bit for optimal-ness, you shouldn't be having that lazy loading problem, especially if it can be solved by a call to Session.Refresh(). Going to take a cue from Paul and recommend heading over to the NHUsers list and perhaps seeing what they can come up with to explain why that may be happening. Note, they don't really use FNH mappings, and if you attempt to post your FNH mappings over there, good chance they'll ask that you come over here. You want to try and solve the issue with them using the XML mappings (which you can get by doing a .ExportTo(//dir) during your FNH Configuration process. If they give you some XML mappings fixes that work for you, you can head over here and we'll figure out how to map those to FNH lingo.

re: CompositeID:
1.) Should handle collections just fine in most cases. Check out this article. There's FNH versions of the NH tags used in it. You should just be able to call .AddKey() to the HasMany() collection to add both of your keys, just like the article shows.
2.) KeyProperty() was what you want, sorry, I was on my mobile and no access to source.
3.) HasManyToMany() should also work with a composite key. That doesn't really change anything, unless there's something else I'm unaware of?

PropertyRef only works with one property, so that's really not going to be your solution here I don't believe. You also can't use a propertyref on the property that's mapped in your CompositeID. propertyref would go away, because you're not doing a propertyref anymore. You're doing a composite key mapping.


To unsubscribe from this group, send email to fluent-nhibern...@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/fluent-nhibernate?hl=en.




--
Reply all
Reply to author
Forward
0 new messages