Hello,
I'm trying to use nhibernate to implement something that seems
straightforward but has become quite intractable. It concerns how to
implement concurrent updates to an entity where it is expected that
the entity will be updated simultaneously by more than one user in a
multiuser scenario. The entity is an account of some kind that has a
balance.

An example is an inventory system that requires updating a balance of
the inventory item based on movement entries in/out applied to it. It
seems quite simple but I just can't resolve how it can/should be done.
I'm also not quite sure it is solely a nHibernate issue or it is a
general issue with multiuser transactions.

I've included below an shortened version of the code below. The
nhibernate mappings would cascade saves from the entry to the entry
lines and from the entry line to the item.

The system should be able to handle multiple users. The entry objects
are created in the UI over a period of time during which time the Item
record cannot be locked pessimistically. The item's balance will be
adjusted from the quantity at the time the entry was created in the UI
which may be several minutes before the final save is attempted. If a
user makes entries on an item and before saving  another user has made
issues or receipts on the same item, the balance that the first user
has is now invalid. NHibernate will throw a stale data exception but
this is not what I want since concurrent access/updates is expected
anyway. What I want is that the current balance of the item be
incremented or decremented as required by the quantity of the entry.
Or that the item be fetched again at the time of update, locked and
updated, but I don't know how this can be achieved in this scenario
and where exactly the code would reside. I would want to avoid it
being in the domain object since controlling pessimistic locking etc
is a persistence concern. It seems this should be a common scenario
but I've not seen anything discussing this.

I'm sure you understand my frustration.

UIController
{
   ISession session;
   Entry entry;
   ItemRepository itemRep;
   EntryRepository entryRep;

   void receiveItem(int itemID, double quantity)
   {
           Item item = itemRep.Get(itemID);
           entry.Lines.Add(new EntryLine(this, item, quantity));
   }

   void issueItem(int itemID, double quantity)
   {
           Item item = itemRep.Get(itemID);
           entry.Lines.Add(new EntryLine(this, item, -quantity));
   }

   void Save
   {
         using (ITransaction transaction = session.BeginTransaction())
         {
               entryRep.Save(entry);
               transaction.Commit();
         }
   }
}

Item
{
   string name;
   double balance;
   IList<EntryLine> entries = new List<EntryLine>();

   public double getBalance() { return balance; }

   void addEntryLine(EntryLine line)
   {
       entries.add(line);
       balance += line.getQuantity();
   }
}

class Entry
{
   IList<EntryLine> lines = new List<EntryLine>();
   public IList<EntryLine> Lines { get { return lines; } }
}

class EntryLine
{
   Entry entry;
   double quantity;
   Item item;
   public EntryLine(Entry entry, Item item, double quantity)
   {
       this.entry = entry;
       this.quantity = quantity;
       this.item = item;
       item.addEntryLine(this);
   }

   public double getQuantity()
   {
       return quantity;
   }
}

-- 
You received this message because you are subscribed to the Google Groups 
"nhusers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/nhusers?hl=en.

Reply via email to