I have a huge object, it has a lot of lazy loadable properties.
I want to enable a quick edit of a very small subset of its property.
How can I, when I just have a few values, tell NHibernate: don't touch anything else?
Because now, when I save, everything not set gets lost.
Have you tried dynamic-update option on your class mapping?
<class name="SomeEntity" dynamic-update="true">
But check if the flush does not cause the unloaded lazy properties to get loaded first, just in case.
In your question, you state you lose other properties. I have never witnessed such a behavior. Are you attaching (using ISession.Update or ISession.Merge) a detached entity in your current code?
What I am suggesting will not work in such a case. It should instead work with an entity loaded from the current ISession, touched on some properties then saved to db only using ISession.Flush (or preferably, ITransaction.Commit, since it is not a good practice to work without transactions).
Related
I need to save a unchanged object via nhibernate to get a database trigger fired.
So how can I tell nhibernate that this object is dirty even if no property has changed?
There are NHibernate extension points, exactly for this scenario. In this case, we can append custom EventListener or introduce an IInterceptor.
Check this question How to make NHibernate considered property to always be dirty when using dynamic update or insert? for a solution (answer based on IInterceptor)
See the NHibernate documenation 12. Interceptors and events
So in respect to my comment to Radims answer I did the following:
I changed one entry of the loadedstate array of the entity so nhibernate will see it as changed on next save.
I know that this is a bit of a workaround but for me it works so far.
EntityEntry entry = sessImpl.PersistenceContext.GetEntry(dbo);
entry.LoadedState[x] = y;
Is there a way to force a managed object into the dirty state? I have a managed object that has a relationship to a parent managed object. If I change a property on the child managed object, I was curious if there is a way to put the parent managed object into a dirty state.
On Mac, you should use NSPersistentDocument for most cases where this would be useful.
On iOS 5+, you should use UIDocument.
If these aren't possible, then you can either have the parent observe changes in its children, or have children set a changed flag on their parent. In either case, you can modify some "last changed" property to cause yourself to become dirty.
You can also create a method like -hasChangedChildren that would walk the children tree and return YES if any are dirty. This has the advantage of not actually modifying the object, so you don't impact any Core Data optimizations. The docs do not forbid modifying hasChanges to behave this way, but I would personally be careful doing so.
But if at all possible, you should use the document classes, since this is what they're for.
You may also be interested in Core Data Questions--Relationships, UUIDs, and Dirty States.
I'm using NHibernate here with C#. I have a cache of nhibernate objects that have lazily loaded objects inside of those that might have changes written to them. I need a way to determine if there are changes that need to be saved. It's quite a lot of effort to set flags when one little thing changes and also quite annoying to compare a cache with a copy of an original (because of the lazy loading).
Just wondering if there's a way I can use the current session object to know if it has pending changes that are about to be written to the db, this is so that I can have a 'do you want to save' prompt if in fact there are changes. I can't autosave, the customer demands a save button.
NHibernate.ISession exposes an IsDirty() method so you should be able to check that.
I am working in a project that's work with N Hibernate. Due to performance issues and increasing in complexity of the project we need to do association manually in our code.As we all know for that we have to set lazy property true. What i want know that, is their any way to do association with set lazy property true.We have already created our own methods for filling Association.But still for that also we need to write many queries and code which is not satisfactory.
Please let me know some way for this.
Thanks.
Lazy loading is turned on by default. There is basically two ways how lazy loading is implemented by NHibernate.
Lazy loading of collections
Lazy loading of "single ended" references (many-to-one)
Collections are easy and straight forward. NHibernate uses its own implementation if the collection classes anyway, lazy loading is implemented there.
Single ended references ("normal" associations) are not that easy. Lazy loading is implemented in a proxy. The proxy is a class created at runtime which inherits from the referenced class. That's why everything in the referenced class needs to be virtual. The proxy overrides every member and makes sure that the data is loaded when a member is accessed from outside. The problem with the proxy is, if you reference a base class, you get a proxy from the base class and you can't downcast it to the real class. So be careful when using lazy loading with inherited classes.
Lazy is turned on by default, you need to explicitly turn it off. So you don't need to do anything special to get lazy loading.
When you are optimizing performance, also consider to use batch-fetching.
for single ended associations:
<class name="xx" batch-size="10">
and on collections:
<bag name="xx" .... batch-size="10">
it reduces the N+1 problem a lot (by factor of 10 in this example.).
I've spent some time searching around how to configure NHibernate's FlushMode so it could only save objects that I've explicity called Save/Update/Delete, but I've figured out that I can't do that. Instead of it, I have to evict every object that I've modified (even without calling Save/Update/Delete) as I'm using NHibernate transaction management.
I understand perfectly why NHibernate have to Flush some objects before some Find operations, but I'm not worried about stale data. I see that, maybe, in some situation, flush everything that was modified and not explicity saved can be usefull, but it's not my case.
I simply want that, after commiting my session, NHibernate inserts/updates/deletes everything that I have explicitly demanded it to, and evict everything else. My question is: is this behavior just a question of "nobody stopped to implement this yet" or are there another points that would fail if this kind of behavior existed?
Thank you in advance.
Filipe
Nhibernate doesn't think that way. The distinction is between transient and persistent objects, and persistent objects are synchronized with the database when the session is flushed (an possibly at other times). Objects that are retrieved using NH are persistent and will be saved when the session is flushed without calling Save (or SaveOrUpdate) because they are already persistent. There are several options for controlling the FlushMode but nothing that would make it work the way you desire.
A potential workaround might be to retrieve objects using an IStatelessSession and handle operations through a separate ISession.
What problem are you trying to solve?
You are basically asking: "why doesn't my hammer work more like a screwdriver?"
The whole idea of the Session (among other things) is to allow automatic dirty tracking, so you don't need to worry about what was changed; only additions and non-cascaded deletions are manual.
As Jamie mentioned you can use IStateLessSession instead of ISession. It does not track anything automatically and it does not support lazy loading. You have to tell it explicitly what to insert, update and delete. It's more used for read-only and batch contexts, but it's probably what you're looking for,