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
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