2


0

NHibernateで増分マルチユーザー更新を行う方法

私はnhibernateをormとして使用し、簡単に見えるが不必要に難しくなったものを実装しようとしています。 これは、マルチユーザーシナリオで複数のユーザーがエンティティを同時に更新することが予想される場合に、エンティティに同時更新を実装する方法に関するものです。 エンティティは、残高がある何らかの種類のアカウントです。

例として、入出庫の移動エントリに基づいて在庫品目の残高を更新する必要がある在庫システムがあります。 以下のコードの短縮バージョンを以下に含めました。 コードは単にエントリを保存し、nhibernateに依存してカスケード保存をすべてアイテムに保存します。

システムは複数のユーザーを処理することが期待されています。 オブジェクトは、一定期間にわたってUIで作成されます。 各アイテムの残高は、UIでエントリが作成され、アイテムが取得された時点の手持数量から調整されます。 ユーザーが最終的に保存するまで数分かかる場合があります。

別のユーザーが同じアイテムで他の入力を行った場合、最初のユーザーが使用している残高は無効になります。 保存が試行されると、NHibernateが古いデータ例外をスローすることを知っています。 しかし、同時更新が必要なので、これは私が望むものではありません。 私が欲しいのは、アイテムの現在の残高が、エントリの数量に応じて増減することです。 または、更新時にアイテムを再度取得し、ロックし、再計算を実行して最終的に更新しますが、このシナリオでこれをどのように実現でき、コードが正確にどこにあるかはわかりません。 悲観的なロックなどの制御はアプリケーション/永続性の問題であるため、ドメインオブジェクトに含まれないようにしたいと思います。 これは一般的なシナリオであるように思えますが、これについて議論しているものは見ていません。

P.S. エントリに多くの行がある状況で、上記で概要を説明したrefetch-lock-recalculate-updateアプローチについて、別の懸念があります。 アイテムごとに個別のロック要求が送信されますか、それともエントリ行のすべてのアイテムのロックを一度に取得する方法がありますか。

任意の助けがいただければ幸いです。

class TestConcurrentUpdates
{
   ISession session;
   Entry entry;
   ItemRepository itemRep;
   EntryRepository entryRep;

   void testMethod()
   {
       ...

       Entry entry = new Entry();

       Item item1 = itemRepository.Get(item1ID);
       Item item2 = itemRepository.Get(item1ID);
       Item item3 = itemRepository.Get(item1ID);

       entry.Lines.Add(new EntryLine(this, item1, 10));
       entry.Lines.Add(new EntryLine(this, item2, -4));
       entry.Lines.Add(new EntryLine(this, item3, 2));
       using (ITransaction transaction = session.BeginTransaction())
       {
           entryRep.Save(entry);
           transaction.Commit();
       }
   }
}


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

   public double getBalance() { return balance; }


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


class Entry
{
   IList lines = new List();
   public IList 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;
   }
}

0 Answer