Difference between lazy loading in NHibernate and Entity Framework - nhibernate

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?

That is how EF POCO template and its FixUp methods behave. The only ways to avoid this are:
Removing FixUp methods from POCO template
Turn off lazy loading temporarily when assigning Product to Order
It is based on the way how lazy loading is implemented. Every access to property / collection itself triggers lazy loading despite of the operation you want to use on the collection. You will have to avoid build in lazy loading completely to fully avoid it. Here is example how to achieve it for Count method - you can think about similar approach for other methods.

I think that calling 'Count' will result in the orders being loaded
unless I configure it as being 'extra-lazy'.
This is correct, calling Count as well as Contains will be optimized and will not load the whole collection in NHibernate. You may also find this EF vs NHibernate comparison interesting:
Collection with lazy=”extra” – Lazy extra means that NHibernate adapts
to the operations that you might run on top of your collections. That
means that blog.Posts.Count will not force a load of the entire
collection, but rather would create a “select count(*) from Posts
where BlogId = 1” statement, and that blog.Posts.Contains() will
likewise result in a single query rather than paying the price of
loading the entire collection to memory.
Adding a new item to an uninitialized lazy collection will not load the collection. It does not have to be mapped as extra lazy for this. Take a look at this article:
Now, on collections mapped as lazy-loading, Add() operations are
allowed even if the collection is not initialized (i.e. the collection
just acts as a proxy). When adding an object to a collection in this
state, a QueueAdd() method is called that stores the added object in a
secondary collection. Once a lazy initialization is performed, this
secondary collection is merged into the main one (I believe it’s the
DelayedAddAll() method that does this). This can be hard to debug
because lazy load is transparently triggered if you just touch the
collection with the debugger (providing the session is connected at
that moment), and everything gets initialized properly.

Related

NHibernate interceptor / hook for Lazy-Loaded collections / Cascade

Lately I have had about enough of creating ViewModel boilerplate code, so I ended up adding the NotifyPropertyChanged-functionality to a DynamicProxy-based solution.
In order to have all of WPF's Changenotification mechanisms working for my implementation, all I have to do now is exchange my Collections with ObservableCollections, which unfortunately brings along a performance issue (change notification for every record added / removed, so not fit for bulk usage because UI gets way too busy trying to keep up with the list of changes).
Thus, In my models, collections of other models (HasMany relationships, that is) are not held within a list, but within a ObservableCollection-derivate that has two Methods SuspendCollectionChangeNotification and ResumeCollectionChangeNotification (A bit like the implementation shown here).
The infrastructure is all there, now I'm looking for an Interceptor hook that enables me to call Suspend() before NHibernate Loads Child data and Resume() after it's done.
I'm a bit afraid I will end up adding this to the proxy I mentioned above, which has a good grasp of the properties that are being requested, but it would be just lovely to keep this in an NHibernate Interceptor...
NHibernate has IInitializeCollectionEventListener which gives you InitializeCollectionEvent when it is loading a collection.
You can hook up like this:
var listener = new YourCollectionListenerImpl();
configuration.SetListener(ListenerType.LoadCollection, adapter);
Unfortunately this only tells you that collection loading is taking place. I don't think it is possible to determine when it is starting and when it has finished.

Enable lazy loading in a query

I have set NHibernate to not lazy load for my entities. But sometimes when I do queries I don't want all the children of the children to be loaded. The mapping is set up by Fluent NHibernate.
Is there any way when writing the sql for the query to specify which columns to lazy load?
I believe, you're using the wrong approach. Set all mappings to lazy load, and then in the queries eager load only what you really need. This way you won't kill the app.
You can override all the mappings defined in Fluent Mappings in conventions either in class mappings.
There also are different scenarios where NHibernate does the trick (for instance if you load / get one instance all the properties will be fetched as defined in mapping. If you get a list of items it will not happen unless you use Fetch method explicitly).
So could you provide some more details on your question to give an answer that is more precise?

NHibernate: removing from collection vs association and cascading styles

I'm having trouble understanding how NHibernate knows anything about objects removed from association (and then execute cascading style like delete-orphant). I mean, at a database level if I wanted to remove an association I'd have to physically log on and remove some FK. How does this happen in NH world? Do I remap my classes, remove previously established parent/child association (relationship), NH does comparative analysis, digs that something has been changed and then takes appropriate action? In this post Ayende talks about different cascading styles and delete-orphat is described as "... In addition to that, when an object is removed from the assoication and not assoicated with another object (orphaned), also delete it ..." How does this removal happen?
NHibernate watches all the mapped collections mapped that are owned by objects in the NHibernate session. As you make changes (adding/removing) NHibernate marks them as dirty. When it is time to flush the changes it compares the elements in the dirty collections and is able to identify what items have been added and removed. Depending on the cascade options for the collection NHibernate might then persist those changes to the database.
This is why you should always declare collection properties using interfaces (IList, ISet, etc.) and never replace a collection property on an object that has been loaded using NHibernate.
Additional info requested in comments:
There is a useful discussion by Fabio Maulo (NHibernate lead developer) of collection mapping here which I would strongly recommend to read. But to try and provide a brief answer to your questions:
But how does NH know that association between objects has been removed?
Generally when working in the OO model with many associations we manage relationships at the parent. That is, a child is considered to be associated with the parent when it is in a parent's collection. E.g.
child.Parent = parent;
parent.Children.Add(child); // This is the critical bit
session.Save(parent); // to have an INSERT generated here
Similarly removing an item from a collection breaks the association (assuming correct mapping attributes have used)
child.Parent = null;
parent.Children.Remove(child); // This is critical bit
session.Save(parent); // To have DELETE or UPDATE statement generated depending on cascade settings.
This is the opposite of how things work in the relational world where we manage the relationship at the child via the foreign key on the child row.
For a more detailed understanding there is nothing like downloading the NHibernate source code, creating a simple test case and then stepping through in the debugger.
What's the reason behind the "This is why..."
There are a number of things NHibernate takes care of in managing in association collections. It does this by using its own collection classes that keep track of whether they are dirty, what state they were in when they were loaded from the db and a number of other cool things. If you replace those objects then NHibernate loses that capability. So, for instance if you want to get rid of all the items in a collection you should do:
parent.Children.Clear(); // The collection object is preserved and NHibernate knows you want them all deleted.
You should NEVER do:
parent.Children = new List<X>(); // NHibernate will not track changes to this collection.
For further reading you might also want to take a look at this.

In Doctrine 2 can the Fetch Mode (Eager/Lazy etc.) be changed at runtime?

I have entities which I would like to eagerly load , and on other ocassions lazy (or even extra lazy) load.
My mappings have no fetch mode declared in my YAML- so they use the default (lazy loading).
Currently the only way to eagerly load is to by constructing the DQL manually - and I need to update this every time I add a new entity.
Ideally I would just load the root entity and the force eager loading all the associated objects. Is there any way I can do this?
If not why (is there a reason beyond it being an unimplemented feature)?
If you want to use built-in repository methods (find(), findAll()), you're probably out of luck unless you set things to eagerly load in your annotations.
You'll probably want to use the query builder (or raw DQL) in some custom repository's method to force eager loading where you want it. Yes, you'll have to update that method as you add entities, but at least you'll always know what's going on in regards to lazy/eager loading, and you'll only need to maintain it all in one place.
I suppose the reason there's not some $eagerLoad flag to find(), etc, is because those are convenience methods for simple tasks. If you wanted to add such a flag, you'd have quickly get into situations where you'd want to limit recursive eager loading by depth. You'd also probably have to start worrying about cyclical references (any bidirectional association, for instance).
You can use setFetchMode() method of DQL to set mode.
See the documentation:
https://web.archive.org/web/20120601032806/http://readthedocs.org/docs/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html

Association in Nhibernate with Lazy true

I am working in a project that's work with N Hibernate. Due to performance issues and increasing in complexity of the project we need to do association manually in our code.As we all know for that we have to set lazy property true. What i want know that, is their any way to do association with set lazy property true.We have already created our own methods for filling Association.But still for that also we need to write many queries and code which is not satisfactory.
Please let me know some way for this.
Thanks.
Lazy loading is turned on by default. There is basically two ways how lazy loading is implemented by NHibernate.
Lazy loading of collections
Lazy loading of "single ended" references (many-to-one)
Collections are easy and straight forward. NHibernate uses its own implementation if the collection classes anyway, lazy loading is implemented there.
Single ended references ("normal" associations) are not that easy. Lazy loading is implemented in a proxy. The proxy is a class created at runtime which inherits from the referenced class. That's why everything in the referenced class needs to be virtual. The proxy overrides every member and makes sure that the data is loaded when a member is accessed from outside. The problem with the proxy is, if you reference a base class, you get a proxy from the base class and you can't downcast it to the real class. So be careful when using lazy loading with inherited classes.
Lazy is turned on by default, you need to explicitly turn it off. So you don't need to do anything special to get lazy loading.
When you are optimizing performance, also consider to use batch-fetching.
for single ended associations:
<class name="xx" batch-size="10">
and on collections:
<bag name="xx" .... batch-size="10">
it reduces the N+1 problem a lot (by factor of 10 in this example.).