2016-04-13 9 views
4

は、このシナリオを想像:NHibernateはIListの(順序付きリスト)競合状態

  1. Anが実体上のコレクションを命じました。
  2. コレクション内の新しいアイテムに対する2つの同時(非同期)CREATE要求
  3. 両方の新しいアイテムが同じ序数を取得します。

コレクションはそうのようなものです:

public virtual IList<CustomField> CustomFields { get; protected set; } 

私はそうのような流暢NHibernateのマッピングがあります。

mapping.HasManyToMany(cp => cp.CustomFields) 
      .AsList(i => i.Column("CustomFieldOrdinal")) 
      .ParentKeyColumn("RegistrationId") 
      .ChildKeyColumn("CustomFieldId"); 

理由はNHibernateのは、次の利用可能な順序を取得するには、DBを照会していることであることをテーブルにロックされておらず、どちらも同じ序数になっています。

これをどのように防ぐことができますか?

+0

実際のユースケースについて詳しく説明できますか?このような問題は、データベースレベルで処理する必要があります(作成するトランザクションを処理する方法を変更する可能性があります)。また、使用しているデータベースを知ることは、使用の情報になる可能性があります。 –

+0

私はSQLサーバを使用しています(azureで)。私のユースケースについては、あなたが知りたいことは何ですか?それはまさに記述されているとおりです。これはdbレベルで最もうまく処理されると思いますか?現在、私はそれを動作させています...私はnhibernateトランザクションでテーブルロックを使用しています、そして、今働いています。 – richard

+1

あなたは「両方の新しいアイテムが同じ序数を得ます」と書いています。しかし、これが効果です。それは「方法」ではありません。どのようにNHibernateに順序番号を生成させるのですか?問題の理由(および可能な解決策)はその中にあります。 「テーブル・ロックを使用する」は、データベース・レベルでそれを解決する1つの方法です。もう1つは、列をデフォルト値で構成し、dbに計算を処理させることです。 –

答えて

0

NhibernateのLockMode.Upgradeでこれを解決しました。これはうまく動作し、問題を解決します。

3

dbのユニークなインデックス/制約がそれを処理します。もちろん、2つのリクエストのうちの1つが失敗した場合に対処する必要があります。

アプリケーション側で例外を処理しないようにするには、そのリストの状態を読み取る(またはdbをリフレッシュする)前に、リストを保持するエンティティに排他的なdbロックを発行することができます(またはISession.Lock(entity, LockMode.Upgrade))。次に、リストを更新します。
リストに挿入するすべてのアプリケーションが同じパターンに従う場合、同じインデックスを持つ要素を同時に挿入することはできません。ロックが解放されるのを待ってから、読み取る前に新しいデータをdbに格納しますそれ自身の新しい要素を挿入します。
これはpessimistic concurrency patternです。続きを読むhere too(リンクはother answerにあります)

楽観的なものでは、行バージョンの列を使用し、リストの更新がエンティティのバージョンに確実に反映されることが必要です。しかし、並行処理の場合は、2つの要求の1つに対して並行処理例外が発生します。

+1

1つのエンティティに対して1-3、もう1つのエンティティに対して1-3を持つことができるので、序数はテーブル内で一意ではありません。また...ユーザーはコレクションを並べ替えることができます... – richard

+1

ユニークなインデックス/制約はもちろん、エンティティidをカバーする必要があります。並べ替えに関しては、NHibernateが変更を発行することによってそれを処理することを願っていますが、それを確認する必要があります。 (私の答えでは、私は 'LockMode'を変更しました、' Write'はドキュメントをチェックするときに良いものとは思われません) –

+0

Okありがとう! – richard

関連する問題