These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 
Author Message
 Post subject: Problem with dirty checking and calculated properties
PostPosted: Fri Sep 07, 2007 11:15 am 
Newbie

Joined: Fri Sep 07, 2007 11:04 am
Posts: 4
I'm using NHibernate 1.2 GA and I have a problem

My Order class has a few properties like this:

public virtual decimal Total
{
get {
decimal total = 0;
foreach (OrderItem item in OrderItems) {
total += item.Total;
}

total += ShippingCost;
total += Tax*total;

return total;
}

set { }
}

You can see that the Total property is calculated based on the OrderItems and other properties of the class. I'm coding the Total this way to avoid having to call a RecalculateTotal method any time a dependent orderItem or property changes.

The mapping for the property is:

<property name="Total" column="total" type="Decimal" not-null="true" />

I can get, insert, update and delete orders, but the problem is that when I get an order, even if I don't change it, it gets updated.

I think this is because of automatic dirty chechking.

The total is stored as decimal(8, 4) in a SQL Server 2005 DB. So when I create an order, if the Total was 1.353433, the value 1.3534 will be stored in the database.

When NHibernate loads the order, the Total returns 1.353433 but when NHibernate loaded the Total, it read 1.3534 from the database, so when the flushing happens, as the value does not match, it forces an update of the order.

Is there any way to avoid this update for my usage scenario?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 07, 2007 7:51 pm 
Hibernate Team
Hibernate Team

Joined: Tue Jun 13, 2006 11:29 pm
Posts: 315
Location: Calgary, Alberta, Canada
When NHibernate loads the entity, the property's value is 1.3534 and this value is "remembered" by NHibernate so that when the session is flushed, it can do a dirty check to see if anything has been changed. When the getter returns 1.353433 even when nothing is changed, NHibernate thinks that the Total property has been changed. Therefore, it issue an update statement to the database.

There are a number of ways around that. The simplest (if you can accept it) is to round the number before you return it from the getter so it will be consistent with what actually got written to the database. Other methods are along the lines of creating a UserType or an interceptor.

_________________
Karl Chu


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 07, 2007 8:15 pm 
Newbie

Joined: Fri Sep 07, 2007 11:04 am
Posts: 4
I have thought of that solution, but it seems a bit hackish.

How would you do it with an interceptor?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 07, 2007 10:57 pm 
Hibernate Team
Hibernate Team

Joined: Tue Jun 13, 2006 11:29 pm
Posts: 315
Location: Calgary, Alberta, Canada
Inherit from the EmptyInterceptor class and override the FindDirty method. See the API documentation of the IInterceptor interface for the precise semantics.

_________________
Karl Chu


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 07, 2007 11:01 pm 
Hibernate Team
Hibernate Team

Joined: Tue Jun 13, 2006 11:29 pm
Posts: 315
Location: Calgary, Alberta, Canada
Actually, overriding OnFlushDirty() probably makes the implementation easier. You may want to explore both options (i.e. OnFlushDirty and FindDirty)

_________________
Karl Chu


Top
 Profile  
 
 Post subject:
PostPosted: Sat Sep 08, 2007 9:17 am 
Newbie

Joined: Fri Sep 07, 2007 11:04 am
Posts: 4
I have looked at OnFlushDirty, but it seems that after an entity has been marked as dirty, there is no way to clean it. This comments are in the OnFlushDirty method:

Note that all flushes end in an actual synchronization with the database, in which as the new currentState will be propagated to the object, but not necessarily (immediately) to the database.

So, I'll look into the FindDirty method for now. Thanks

BTW, It is a shame that there aren't any post events in the IInterceptor interface.

Thanks


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 29, 2008 10:35 am 
Beginner
Beginner

Joined: Mon Mar 26, 2007 5:47 am
Posts: 22
Hi manunews,

Did you find a solution? If yes: could you post it here?

Thanks,


Pieter


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
cron
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.