Implement own IsDirty in nHibernate - 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

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.

NHibernate lazy loading. Retrieve data on demand

I have some class with associated list. I want this list not to be loaded when I retrieve the entity, but I want to have an opportunity to load this list later, outside the session in which I cought the entity.
Can NHibernate's lazy mechanism do this?
Thanks!
In theory you can implement your own IBytecodeProvider / ProxyFactory and do whatever you want. But that's quite complex, so you'll want to stick to regular NHibernate usage, which dictates that lazy loading requires an active session. It can be the originating session or you can reattach an entity from a previous session using ISession.Lock()
From outside of the session, you will always get an exception when you access an not-yet loaded object.
There is a way to get your objects from a new session. What you want to do is known as "Remote Lazy Loading". See http://www.theserverside.com/news/1363571/Remote-Lazy-Loading-in-Hibernate

NHibernate Rollback w/ broken rules (validation best practice)

I'm working on a legacy system that is using the enterprise library validation block to add a broken rule when an object is not valid. Then the user is returned a message based on this error and told the object was not updated.
The only issue is that now I'm using NHibernate to persist these objects -NHProf shows an update to the object when I commit the session. This is because the object has been modified I assume and the ORM is simply doing its job.
My question is this - what would be the best way to check for these broken rules before I commit the session? Or should I not use Enterprise library and switch to something NHibernate friendly?
Update
I came across this event listener class for the NHibernate Validator Event Listener - my final implementation was very similar
I'm not familiar with the enterprise validation block, but can't you write an interceptor or something like that which can be used to determine whether the object can be saved or not, based on the information you have regarding the broken rules ?
You can also choose not to use the automatic dirty checking of NHibernate.
This means that you'll have to call 'Save' yourself on an object you have modified in order to get that object saved.
You can get this functionality via NH Addins

NHibernate - problems with validation and transactions

I'm using NHibernate as my ORM. I have a situation where I have some stuff wrapped in an ITransaction. I am listening to the SaveUpdate event in NHibernate and then doing my entity validation in that SaveUpdate handler.
For one of my entities, I want to validate that the value of a certain property hasn't changed. So I figured that I would load up the value of the existing object from the database and compare it with the new value. The problem is that I called ITransaction.Commit() to save my entity object and the transaction hasn't actually been committed at the time that validation occurs, so I can't load the existing object from the database because the transaction has it locked.
So I guess I have a few different questions here:
- Is the SaveUpdate event the correct place to do validation?
- Is there another way I can do this so that I can do the validation that I need to do (getting the existing value from the database and comparing)?
I'm sure someone else out there has run into a similar situation...... hopefully!
If you want to see an example of how to do validation, I suggest checking out ScottGu's NerdDinner. Although he's using Linq to SQL for his ORM, it's very easy to adapt it to NHibernate.
I recently used a validation system similar to the NerdDinner one in an ASP.NET MVC + NHibernate project with great success.
Validation has nothing to do with persistence, so saveupdate is not the right place. The correct place of validation depends on: what you want to validate, your programming style, the UI framework you use to show the validation messages, etc. Personally, I prefer to put the validation on the place where things are changed, so I would put it in the change method that sets the property. I don't understand why you want to load the entity in the previous state, because that state is already loaded when you load it for the first time.

Using NHibernate to determine which fields have been updated (for validation purposes) before persisting

Prior to persisting updates to my business entities, I need to perform validation checks to determine which properties have been changed. For example, certain fields can only be updated when the "Status" property has a particular value. E.g. when an Order entity has a Status of finalized, only the notes (string) field can be updated. Is this sort of thing possible using NHibernate, or should I be tracking the changes myself in the Business entities?
If I understand what you're trying to do, Gabriel's solution is not quite what you need. If it is not, you can try an event listener. Those allow you to hook into a common event (like on save) and do some processing before NHibernate finishes the save/insert/update/delete. Alternatively, you could look into using interceptors by implementing the IInterceptor interface.
This sort of thing is indeed possible. Coding Instinct has a great post introducing NHibernate.Validator.