What’s the proper way to reference entities which were already persisted in a different session, but remained unchanged in memory after a session has been closed?
Once NH persists an entity in a single session and that session is closed, I need to fetch it again in a new session in order to reference it in some other transient entities. Or, I can call Session.Lock on the new session instance and let NH know this entity is not transient. This item should never change during app lifetime.
What would be the preferred way to use? Is there some other way to do it?
[Edit]
Additional problem is that I am using the Repository pattern, and not using NH directly in my business layer. This means that I also need to have a way to abstract this call to Session.Lock, i.e. have a method similar to Session.Lock in my repository interface. This is a bit smelly IMHO.
Concerning the first question. If you are just going to read the entity, you don’t have to do anything. Even assigning it as a field to a different entity will not require you to lock the record. The only reason you need to call
ISession.Lockis when you want to mutate and then save the entity.There is an exception and that is lazy loading. If the entity has foreign child records that were not loaded while the first session was active, an exception will be thrown when you try to access them later on. The easiest way to get around is, is to touch the child collections in first session.
If the entity is still giving you problems under these circumstances, you can add a
Loadto your repository. You can wire this toISession.Load. WhatLoaddoes is create an empty proxy for the entity without hitting the database. This entity is a part of the session the entity is loaded with and can be used to assign to properties of other entities. The advantage of this approach is that it’s a lot cleaner and it’s easy to mock with unit testing.Concerning the second question. Yes, you’re right that it smells to integrate
ISession.Lockinto a repository. Again, when you don’t have to mutate the entity, you don’t have to worry about this. But, when you are, well, you really should think about just re-loading the entity from the repository and work on that one. I know it’s not as optimal as could be, but it saves you a lot of very strange code, specifically in your unit tests.One last thing. I understand that you’re talking about an entity that will live for a long time (maybe the full runtime of the application). You have roughly three categories of lifetime: 1. forever, 2. long and 3. short. The reason I mention this is that more than once, problems with entities that have a ‘long’ lifetime could really just stay connected to a session that has the same lifetime. It’s not a problem to have a session alive for say, 5 or 10 minutes (the time the user is entering data in a form). This alone will save most people a lot of trouble.
One more note: have a look at
NHibernateUtilandNHibernateProxyHelper. These classes can help you force loading of entities and child collections.