Inverse bi-directional bag initialized on .Add?

0 views
Skip to first unread message

Francisco A. Lozano

unread,
Sep 9, 2009, 7:44:46 AM9/9/09
to nhu...@googlegroups.com
Hi,

I have an entity named Users, which has a one-to-many relation with
another entity called Relationship. It is mapped as a bi-di bag.

With my just-purchased NHProf license (thankyou Ayende!) I'm checking
my most-common use-cases against future performance problems.

I have a CreateContact method in User, which creates an instance of
Relationship and adds it to its Relationships collection.

With NHProf I've just noticed that NHibernate is initializing the
"Relationships" bag on Users when I do ".Add" on that property!
Why does it do it? I thought that <bag /> semantics didn't require to
initialize ... or at least in Java-Hibernate I remember moving from
<set ..> to <bag ...> in many places because of this very issue...

My classes and mapping:

public class User : Entity
{
....
public virtual ICollection<Relationship> Relationships { get; set; }
....
public virtual Relationship CreateContact(User user, string message)
{
if (Relationships == null)
Relationships = new List<Relationship>();

Relationship r = new Relationship()
{
Message = message,
Contact = user,
Owner = this
};
Relationships.Add(r);
return r;
}
....
}


public class Relationship : Entity
{
....
public virtual User Owner { get; set; }
....

<class name="W.Domain.Users.User, W.Domain">

<id name="Id">
<generator class="hilo" />
</id>

<timestamp name="ModifiedAt" />
<property name="CreatedAt" not-null="true" />
.....
<bag name="Relationships" inverse="true" lazy="true"
cascade="all-delete-orphan">
<key column="owner" />
<one-to-many class="W.Domain.Users.Relationship, W.Domain"/>
</bag>
....

</class>
<class name="W.Domain.Users.Relationship, W.Domain" >
<id name="Id">
<generator class="hilo" />
</id>
<timestamp name="ModifiedAt" />
<property name="CreatedAt" not-null="true" />
<property name="Message" length="250" not-null="false" />
<many-to-one name="Owner" class="W.Domain.Users.User,
W.Domain" not-null="true" unique-key="AK_OWNER_CONTACT" />
<many-to-one name="Contact" class="W.Domain.Users.User,
W.Domain" not-null="true" unique-key="AK_OWNER_CONTACT"/>
<many-to-one name="Reciprocal"
class="W.Domain.Users.Relationship, W.Domain" not-null="false" />
</class>

This is the "offending" SQL:

SELECT relationsh0_."owner" as owner5_1_, relationsh0_."id" as id1_1_,
relationsh0_."id" as id1_4_0_, relationsh0_."modified_at" as
modified2_4_0_, relationsh0_."created_at" as created3_4_0_,
relationsh0_."message" as message4_4_0_, relationsh0_."owner" as
owner5_4_0_, relationsh0_."contact" as contact6_4_0_,
relationsh0_."reciprocal" as reciprocal7_4_0_ FROM "relationship"
relationsh0_ WHERE relationsh0_."owner"=@p0

Francisco A. Lozano

Francisco Lozano

unread,
Sep 9, 2009, 8:44:28 AM9/9/09
to nhusers
The manual confirms my case:

17.5.3. Bags and lists are the most efficient inverse collections

Just before you ditch bags forever, there is a particular case in
which bags (and also lists) are much more performant than sets. For a
collection with inverse="true" (the standard bidirectional one-to-many
relationship idiom, for example) we can add elements to a bag or list
without needing to initialize (fetch) the bag elements! This is
because IList.Add() must always succeed for a bag or IList (unlike an
ISet). This can make the following common code much faster.



Any hint?

Fabio Maulo

unread,
Sep 9, 2009, 9:03:37 AM9/9/09
to nhu...@googlegroups.com
try to recreate the issue without the code and the mapping inside your "...".

2009/9/9 Francisco Lozano <flo...@gmail.com>



--
Fabio Maulo

Francisco A. Lozano

unread,
Sep 9, 2009, 10:02:01 AM9/9/09
to nhu...@googlegroups.com
I've created a sample project with the same logic and it clearly works
as expected, so I can't :/.

Better than that, now I've gone to the main project and tested it
again, and NHProf shows that it works as expected, too, but I haven't
changed anything!!

Maybe it was me unintentionally expanding that property with the
debugger... don't know... Will take a deeper look at it.

Thanks anyway and sorry for bothering you all

Francisco A. Lozano

Fabio Maulo

unread,
Sep 9, 2009, 10:05:39 AM9/9/09
to nhu...@googlegroups.com
2009/9/9 Francisco A. Lozano <flo...@gmail.com>


I've created a sample project with the same logic and it clearly works
as expected, so I can't :/.

ahahahahahah LOL ... well now you know where is the problem ;) ... have a look to the code/mapping inside the "..." you sent here.


Better than that, now I've gone to the main project and tested it
again, and NHProf shows that it works as expected, too, but I haven't
changed anything!!

Maybe it was me unintentionally expanding that property with the
debugger... don't know... Will take a deeper look at it.

aaaaaahhhh for sure... inside debugging NH is running and if you try to see a collection the debugger will initialize it.
 
Thanks anyway and sorry for bothering you all

No problem, this thread can be useful to somebody else ;)

--
Fabio Maulo
Reply all
Reply to author
Forward
0 new messages