This issue has had me perplexed for some time now. If anyone could shed some light on how to achieve the following, I would be extremely grateful.
I have a WinForms app, which uses the standard TreeView/ListView layout (like Windows Explorer). As you can imagine, objects are drawn in the treeview so that child objects appear as subnodes. Whenever the user clicks a treenode, an editable listview is populated with the properties of the selected object:
Code:
Customer 1
|- Addresses
| |- Address 1
| |- Address 2
| |- Address 3
|
|+ Orders
The user may modify the objects in any order they wish, so they might do this:
1) User edits Customer.Name
2) User edits Address1.ZipCode
3) User saves/commits Address1
4) User cancels Customer
If I use one session to read/write the objects, the changes to the Customer object get persisted, even though they shouldn't. I've tried to tackle this by using 2 sessions - a main 'read-only' session, and a temporary 'save' session:
Code:
ISession mainSession = SessionFactory.OpenSession();
object load(object obj)
{
return mainSession.Load(obj);
}
void save(object obj)
{
ISession saveSession = SessionFactory.OpenSession();
ITransaction txn = saveSession.BeginTransaction();
// Move the object from the main session into the local session:
mainSession.Evict(obj);
saveSession.Lock(obj);
saveSession.SaveOrUpdate(obj
txn.Commit();
// Move the object back into the main session:
saveSession.Evict(obj);
mainSession.Lock(obj);
}
This doesn't work either. Because the object isn't modified in the 'save' session, NH doesn't detect any changes, and therefore nothing gets saved to the database.
Some other points to note:
a) I want to keep the idea of a 'read' session. Not only does it act as a cache, but if a save operation fails in a different session, I don't have to discard all of the other objects that the user might have loaded.
b) I have tried using the 'command pattern', where I record all of the changes made to the domain objects, and replay them within a 'save' session. The danger is that I could potentially end up calling code twice (e.g "Send an email when the order status has been updated" should only happen once).
Does anyone have ideas on how to accomplish this? Or is beyond the scope of what NHibernate can currently do?