Unit Of Work Behaviour in NSB7


(Gursharan Singh) #1

Hello, We are upgrading from NSB5 to NSB7. And I am a bit confused about Unit Of Work behavior.

  1. Are behaviors singletons or container scoped?
  2. How do I get access to Sql Persistence connection (outbox is enabled) in a “public class UnitOfWorkBehavior : Behavior”?
  3. How do I get access to my nested container instance so that I can setup my NHibernate session correctly for rest of the services in the above Unit of Work?

Thanks in advance!
Gursharan


(Ramon Smits) #2

Behaviors are single instances / singletons. As behaviors are reused and must be stateless.

If you need to resolve anything then this can be done via via the context argument of the Invoke method.

var builder = context.Builder;
var thingy = builder.Build<MyThingy>();

Make sure to also release in a try..finally:

builder.Release(thingy);

The NHibernate session is already managed by NServiceBus and provided via:

var session = context.SynchronizedStorageSession.Session();

What do you need to ‘setup correctly’ on the NHibernate session?

– Ramon


(Gursharan Singh) #3

Thank you for your quick response.

I am using Sql persistence so context.SynchronizedStorageSession.Session() will not give me NHibernate session i think.

To inject ISession into my services, I was hoping to do something like

nestedContainerInstanceForTransportMessage.For.Use(session).

For this,

  1. I need to be able to get the nested container instance in the behavior but with a singleton behavior I am not sure how to get this
  2. I need to create a NHibernation ISession using same connection/transaction as sqlpersistence.

(Daniel Marbach) #4

Hi Gursharan,

The builder you get on the context is the child builder but it cannot be modified. If you need to inject ISession into your services you have to either explicitly pass it to the services over method injection starting from the handle method or you need to create a binding on a func on the root container that resolves the session on-demand from an AsyncLocal that is set in a behavior.

It is very similar to the guidance we wrote for IBus

https://docs.particular.net/nservicebus/upgrades/5to6/moving-away-from-ibus#dependency-injection

and you can have a look at how it is done with the UniformSession extension

AsyncLocal requires .NET 4.6.1

Regards
Daniel


(Ramon Smits) #5

To add to the information of @danielmarbach is that it seems you want to create your own NHibernate session based on the existing connection accessible via the context. Unfortunately, by default that isn’t possible with NHibernate. NHibernate can join/enlist to an existing TransactionScope but as these are not used you only have access to an existing IDbConnection and IDbTransaction which are managed by the SqlPersistence session.

You cannot create an NHibernate session based on a IDbConnection that already has a started a transaction. This is a NHibernate limitation. Maybe this can be resolved by using a custom factory to resolve the existing IDbTransaction but I’m not aware of any.


(Gursharan Singh) #6

Thank you Daniel for pointing me to the blog post and code sample.


(Gursharan Singh) #7

Thank you Ramon for pointing this out. I guess if we take NH dependency then we must use NH persistence to keep everything in one tx vis-a-vis outbox etc. With sql persistence, we would have to use something else or just plain ADO.NET.