While playing around with the Entity Framework and NHibernate using POCO entities, I made the following observation which I find a bit unusual:
I have two POCO entities, an 'Order' and a 'Product'. There is a many-to-many relationship between the two. When I add a product to an Order, I use a 'FixUp' method to ensure that the opposing side of the relationship is also updated i.e. - that the products collection of 'Orders' is also updated.
My Order POCO entity has the following method to do the 'FixUp':
private void FixupProducts(object sender, NotifyCollectionChangedEventArgs e)
{
if(e.NewItems != null)
{
foreach(Product p in e.NewItems)
{
p.Order.Add(this);
}
}
}
While profiling this scenario with EFProf and NHProf, I observed that the Entity Framework generates one more SQL statement than NHibernate, the cause of which seems to be this line:
p.Order.Add(this);
With Entity Framework, the above line causes a select to be executed on the database to return all the orders for the product 'p'. I don't expect this to happen, since I'm using lazy loading and don't actually want to access the products 'Order' collection. I just want to add an order to it.
With NHibernate no attempt is made to load the products collection of orders unless I explicitly try to access it. For example, if I say:
foreach(Order o in product.Orders)
{
Console.WriteLine(o.Id);
}
So ultimately my question is, why does Entity Framework generate the extra SQL statement? Is there a difference in the implementation of lazy loading for the two frameworks that I'm not aware of?
***EDIT TO ORIGINAL It seems that Entity Framework doesn't behave in a lazy fashion once a method of any kind is called on the collection. Any attempt to add or count (or presumably any other operation on the collection) results in that collection being loaded into memory.
What's interesting is my NHibernate mapping (which is a bag of 'Products - shown below), appears to behave in an 'extra-lazy' fashion, even though my mapping is configured as just being lazy:
<bag name="Products" cascade ="all" table="OrderProduct" mutable="true" lazy="true">
I can 'Add' to the collection without it being loaded into memory. I think that calling 'Count' will result in the orders being loaded unless I configure it as being 'extra-lazy'.
Can anyone comment on whether this is correct?