Get list of changed fields in Entity from NHibernate Session - nhibernate

I want to track changes in my domain model. I know that NHibernate ISession is an inmplementation of UnitOfWork pattern, so it tracks this changes. Is there any way to pull out them, for example, before Commit() or Flush()?

Take a look at NHibernate's IInterceptor.
OnFlushDirty - will show you persisted properties on an updated object.
OnSave - will shows you persisted properties on a saved object.
You just need to create an interceptor class that implements this interface, and when you configure your NHibernate session, tell it to use that class.
Here is a fairly good article to help you get started

I think than Interceptors are a little bit obsolete. Š•rying to use NHibernate Events. I've subscribed on OnPreUpdate event. It's parameter has State and OldState properties, but OldState is allways null. Does anyone know this OldState works at all?

Related

Force NHibernate to get entity that is already in persisted state / 1st level cache

I have a service object that is responsible for some business logic validation. What it does, before issing Update to repository, is checking whether entity that it works on complies to some business rules.
One of that rules that is must check is if Status property of the entity didn't change when compared to entity that is in database. Because I use repositories that share the same ISession, when I try to get entity from database, in order to get an object for comparsion:
if (fromDbEntity.Status != entity.Status) throw new Exception("Cannot change status...");
I'll always get fromDbEntity that is in 1st level cache - so I work on the same object.
Is there a way to force NHibernate/Repository to get entity from database even though it's already in the scope of the session?
Evict entity from session before loading fromDbEntity
session.Evict(entity);
You can check the official documentation for more details: Managing the caches
The con about this is that you will need to manually call SaveOrUpdate for entity since now the object is out of the session.
You could, as Claudio suggests, evict the entity from the session, then load your fromDbEntity, do the comparison and then Merge the entity again with the session.
Other thing you might do is loading the fromDbEntity using the stateless session instead.
But is this really necessary? Couldn't you just make your Status property read-only? NHibernate is perfectly capable of using fields for accessing data. Or you could make your property setter protected:
public virtual Status Status { get; protected set; }
This way the user won't be able to change the property value, so there's no need to check whether current value is different from db one.
I had a similar issue, I solved it by clearing the session before any call that I want to go all the way to the data base.
session.Clear();
It's a little overkill but it works.
The way you sate your logic, it sounds like there's a potential bug. A much better solution would be to turn on dynamic-update, thus only updating changed values, then validate that no one has changed Status before saving.

Can I control the insert/update-command of (fluent) nhibernate to call a webservice instead of writing into the DB?

I want to use fluent-nhibernate to query my data, but when a entity gets saved, it should not be written into the database via insert/update. Instead, I want to (better: have to) serialize that object and send it to a webservice (which will map that object to a 3rd-party class that will trigger some important business-logic).
Is such behaviour possible to implement with nhibernate (call a custom method instead of update on saving)?
I would recommend creating a IRepository interface and hiding the webservice and Nhibernate functionality behind that. You could possibly use NHibernate interceptors for this, but it doesn't sound like a clean solution. Personally, I would hate to find Web service code hidden in one of Nhibernate interceptors.
We decided to use a SaveOrUpdateEventListener for this task.

NHibernate - How to Iterate Persistent Entities Attached to a Session?

I have a need to inspect the set of attached entities that would be persisted if I called Flush() on a given session. (I'm writing code that accesses a Session as part of a generic pipeline before saving and it can be used in any number of contexts.)
I find myself wishing that there were a method like
mySession.GetPersistentEntities()
so I could inspect them and perform some preprocessing.
Anyone know of a way to do this?
Thanks,
Jeff
No, NHibernate's ISession does not expose anything like that. You can either:
Track these instances yourself (not recommended)
Use standard NHibernate mechanisms:
Event listeners (e.g. IFlushEventListener, ISaveOrUpdateEventListener)
Interceptors (IInterceptor.OnFlushDirty(), OnSave())
You could "hack" a little bit into the session context:
ISession session;
var sessionContext = session.GetSessionImplementation().PersistenceContext;
foreach(var entity in sessionContext.EntitiesByKey.Values)
{
// do anything with the entity
}
However, in your case I would use flush event listeners or an interceptor.

Ninject / NHibernate Events + Observer Pattern

I am trying to implement an observer pattern using ninject and NHibernate.
I'd like to be able to inject observers that act as "triggers" when an object is persisted or deleted via NHibernate.
Key points-
I want the observer to be notified any time an object is persisted, including cascaded saves, which is why I am using NHibernate PostInsert/PostUpdate events.
I want to be able to inject the observers via Ninject (don't want the kernel anywhere in the nhibernate event handlers).
The observers are different depending on the type of the object being persisted, so I need a good way to know which observers should be called in the NHibernate events.
My code works great now for objects that are loaded via NHibernate using constructor injection. An observer class is injected into the domain model, which is carried through the nhibernate events and can be fired off no problem.
The problem: Our existing codebase uses default constructors for our domain objects versus a factory. Because of this, the observers will not be injected unless we switch to using a factory.
I know that switching everything to a factory will work, but I wanted to see if anyone has any better suggestions for accomplishing this. So, should I make a factory to instantiate new objects or something else?
It looks like you are making life complicated for yourself by trying to put Observer pattern on top of NHibernate's Event Handler pattern.
NHibernate already provides a way of having pluggable event listeners - why not just make use of that?
class FooPostInsertEventListener : IPostInsertEventListener
{
public void OnPostInsert(PostInsertEvent #event)
{
var entity = #event.Entity;
var entityType = entity.GetType();
if (entityType != typeof(Foo)) return;
ProcessFoo(entity);
}
}
If you are desperate to go through the Kernel, then you can even use the Kernel when configuring NHibernate. Something like this:
config.EventListeners.PostInsertEventListeners = Kernel.GetAll<IPostInsertEventListener>().ToArray();

Implement own IsDirty in nHibernate

For my current project, we use a nHibernate session to retrieve the object, and another session to update the changes we've made to the object in between the two session. If we use SaveOrUpdate(), nHibernate will typically do a select-then-update (so, two calls to the database).
However, our own business objects already keep track of changes. So, we'd ideally want to intercept within nHibernate and vote whether the object has been changed or not (without letting nHibernate do the select-statement).
Would that be possible with an interceptor?
You can use your own custom Persister.
Check this - https://www.hibernate.org/161.html
with the interceptor you can intercept all querys and change then or add some sql to
don't now if you can stop nhibernate for doing a select query