tags:

views:

581

answers:

3

I have a call that needs to determine if a field has changed. But calling get using that entities id returns the same entity not the prior version.

Entity e = Dao.Get(id);
//At this point e.Field is X
e.Field = y;
Dao.Save(e);

Entity Dao.Get(Guid id)
{
  return Session.Get(id);
}

Entity Dao.Save(Entity e)
{
   Entity olde = Session.Get(e.Id);
   if (e.Field != olde.Field) <--- e.Field == olde.Field so it does not run.
     DoBigMethod(e);
   return e;
}

How do I handle this situation without adding an onChange method to the Entity class.

+1  A: 

You only know one "version" of the entity: the current one. There is actually only one version of the entity. You have it in memory and you already changed it and forgot the previous state.

Call get to see the previous database state is dangerous. If changes are already flushed (NHibernate flushes before queries for instance), you get your changes. If you open another session, you see changes from other transactions.

Are you only interested in one single field? Then you can cache the old value somewhere.

If this wouldn't work, you need to tell me more about the reason why you need to know the previous value of this field.

EDIT:

Some more ideas:

  • cache the previous state of the field when you get the object, in DAO.Get
  • implement this property that it sets a flag if it changed.
  • consider to make this change an explicit operation called by the client, instead of an implicit operation that is called when the flag changes. For instance, if this flag is called "Activated", implement a "Activate" and "Deactivate" method. This methods change that flag and perform the "large set of code". The flag is read-only for the rest of the world.
Stefan Steinegger
We have an flag on a user that if it changes runs a large set of code. This code will throw exceptions in certain cases. I do not need to do this check if they are just updating other fields. Exceptions would be unlikely in those cases.
Thad
I added some more ideas to my answer. Hope it helps.
Stefan Steinegger
A: 

Fetching a second entity from the db is not necessarily a bad idea. In an "Open Session In View" type of architecture, were all read/writes are contained in the same transaction I would agree with Stefan. In a detached entities architecture were entities outlive their read transactions, fetching a second entity is unproblematic. If you use a flag within the entity to indicate that it has changed, what if the change actually equals a change done by another user since your last retrieval of the entity? If your opting for performance or using an "Open Session In View" architecture, go for solution 1. If you have detached entities and its crucial that the "DoBigMethod" is only executed if the entity differs from the values in the db at save time, start a transaction, fetch a second entity from the db and compare it. Please note that if your using the singleton session (anti)pattern than this approach will not work.

Marius
A: 

I am working on WMS project.Now we open sessionB for Nhibernate when page loads for a particular table or in some more place in S/W.Now I make changes to table from some different form which has its own sessionA and now SessionA changes are not reflected because previous form is not closed.So to reflect I need to close form at each place n see changes.I dont see changes even on refresh..because it doenst load new value from Database...This happens in many places in entire S/W..What shall i do..?Please Help..

Jasma