views:

117

answers:

2

Hi,

This seems like it would be a common issue to be but I don't know the best way to solve it. I want to be able to send an Entity to a view, have changes be made to the entity in the view, but then cancel (remove) those changes if the user cancels out of the view. What is the proper way to do this.

Here are two options I have but I think there should be others that are better

1) Take an entity, create a clone, send the clone to the view...if changes are accepted, update the original entity with the clone's values

2) Send the entity to the view, if the user cancels, remove the entity from NHibernate's cache and reload it from the database

For (2), the issue for me would be that the old entity could still be referenced throughout my project after it has been removed from the cache.

Edit:

Ok, so the evict method is the way to go if I am implementing method (2). Thanks, I could not remember the details of that one. However, the issue of view objects referencing my old evicted entities makes the issue tough to deal with. I can't just have my view automatically update to a new entity without having custom code in each one to rebind when my custom eviction event is raised. And rebinding may not be trivial in certain cases. I need to think on this some more as I may be over complicating but at the moment, this method seems trickier.

I suspect I am going to be stuck with method (1) which has its own set of problems but will wait a bit longer to see if anyone else has some ideas.

Edit 2: Just found this. I think it pretty much covers the answer in detail and comes with a great demo project - Building a Desktop To-Do Application with NHibernate - http://msdn.microsoft.com/en-us/magazine/ee819139.aspx

In addition to this, NHibernate has a Session.Refresh(Object entity) function which seems to solve the exact problem. So, when an entity is changed but then cancelled before save, I can just call Session.Refresh to reload it from the database and discard the changes.

+1  A: 

The best way to do this is to call the Evict method on the ISession used to load the object. This will remove the object from the session cache. and you can then reload and redisplay it.

Evicting the object from the session makes it transient detached so if there are still references to it in the project they will not be persisted when the session is flushed. How you deal with that depends on your application but I would suggest raising an event to notify subscribers that they need to re-load the object.

Jamie Ide
A: 

I'll go for option 1 and use what is called a ViewModel instead of your entity. The ViewModel is representation of you model for a specific view. In the ViewModel you can mix data from different entities and pre-format values to fit the view. Is an elegant way of passing data to a view and you can accomplish what you want easily.

Using ViewModels is becoming the preferred way of working in ASP.net MVC and Silverlight / WPF.

To read more about Viewmodels: http://blogs.msdn.com/dphill/archive/2009/01/31/the-viewmodel-pattern.aspx

Ariel Popovsky
I have ended up somewhat using this solution. I don't find it ideal though because sometimes my entities contain exactly what should be in my view and I don't like having to copy their properties over to something else. Still, seems to be ok for the most part. Thanks
i8abug
In the end you'll get used to it. I recommend using Automapper to ease the pain of copying data back and forth.http://automapper.codeplex.com/
Ariel Popovsky