Get individual collection item from persistent saga data [NHibernate]

nhibernate

#1

Hi

I am using a NServiceBus Saga with a SagaData class that contains a dictionary.
Whenever a Saga’s handle is called I want to check the dictionary for the existence of a certain object.
However, I realized that in this case NHibernate completely loads the dictionary requiring to query each item in this dictionary.
Since my dictionary contains about 2000 items, this is rather slow.

Apparently there are several NHibernate solutions for this problem but I can not get them to work in the NServiceBus setting.
According to http://nhibernate.info/doc/nhibernate-reference/collections.html one can use CreateFilter() to retrieve a subsets of a collection without needing to initialize the whole collection.

To start, I tried retrieving the count as the hibernate reference suggests:
var count = s
.CreateFilter(Data.Documents, “select count(*)”)
.UniqueResult();

Data is my SagaData and Documents is a Dictionary<Guid, Document>.
Document is a user defined class.

In this case, Hibernate throws a HHibernate.QueryException: ‘The collection was unreferenced’.

Can anyone help me there? I use the out-of-the-box NHibernate configuration with no custom mappings etc.
Thank you.


(Ramon Smits) #2

You shouldn’t be using NHibernate specific queries within your saga. You don’t have access to the NHibernate session within the saga and trying to workaround this should not be done.

A couple of options:

  1. Maybe you can redesign your saga. For example, have a saga per collection instance or store this item outside of a saga. In general sagas only maintain a specific consistency boundary. In the saga you could for example only store an ID, and via a handler store the details of the item for that specific ID.
  2. Create a different custom mapping that allows “extra” lazy loading which has a specific override for counts NOT to fetch the actual collection items.
  3. Maybe even the simplest, have a property on your saga that contains the size of your collection so that when you want to know the size that this is already stored as a row value without needing to query collection for a count or fetching the items.

But… be sure to not make your sagas contain lots of data. If parts of the data can be stored independently because there is no reason to guard the whole structure consistence then do so. This will result in less IO, less optimistic concurrency issues and thus faster processing.

Does this help?

– Ramon


#3

Hi ramonsmits

First of all, thank you very much for your detailed answer.

I was able to solve this problem by reducing the amount of data stored in the collection. I also added a counter as you suggested in 3).

These two things already speed up dictionary access (which was actually my number one issue, the count was only an example) tremendously.

Thanks again
Best