3

集計ルートで計算されたプロパティを永続化する必要があります。計算は子エンティティに基づいています。ルートを使用して、ドメイン メソッドを介して子を追加/削除しています。これらのメソッドは、計算プロパティを更新します。

子エンティティは、システムの複数のユーザーが特定のルートに追加できます。たとえば、UserA は子を Root123 に追加でき、UserB も子を Root123 に追加できます。

複数のユーザーが異なるトランザクションで同じルートに子エンティティを追加している可能性がある場合、この計算されたプロパティが正確に保持されるようにするにはどうすればよいですか? 私の特定のケースでは、ルートの別のプロパティによって設定されているように、計算されたプロパティを使用して、制限を超えないようにしています。


問題のより具体的な例を次に示します。

public class RequestForProposal : AggregateRoot {
    ...
    private ISet<Proposal> _proposals = new HashedSet<Proposal>();

    public virtual int ProposalLimit { get; set; }
    public virtual int ProposalCount { get; protected set; }

    public virtual IEnumerable<Proposal> Proposals {
        get { return _proposals; }
    }
    ...

    public virtual void AddProposal(User user, Content proposalContent) {
        if (ProposalCount >= ProposalLimit) {
            throw new ProposalLimitException("No more proposals are being accepted.");
        }

        var proposal = new Proposal(user, proposalContent);
        _proposals.Add(proposal);
        ProposalCount++;
    }

    public virtual void RemoveProposal(Proposal proposalToRemove) {
        _proposals.Remove(proposalToRemove);
        ProposalCount--;
    }
}

2 人のユーザーがほぼ同時に提案を送信した場合はどうなりますか? UI は、まだ制限に達していないことを確認し、両方のユーザーに提案を送信するための Web ページを表示します。最初のユーザーが送信すると、すべてがうまくいきます。これで、最初のユーザーが 2 番目のユーザーの前に送信する限り、2 番目のユーザーは問題ありません。2 番目のユーザーが送信すると、DB からデータが取得され、制限が正確になります。

これは論点ですか?2 人のユーザーがほぼ同時に送信するまれなケースでは、DB の制約 (ProposalLimit >= ProposalCount) に依存する必要がありますか?

4

1 に答える 1

2

ビジネス ルール チェック (リミット チェック) をトランザクション内に配置する場合は問題ありません。あれは

  1. ユーザーが [提案の追加] コマンドを起動するボタンをクリックした場合
  2. コードは新しいトランザクションを開始します。トランザクションの使用方法については、こちらを参照してください
  3. データベースから RequestForProposal オブジェクトをロードするか、リフレッシュします。アップグレードロックを使用することをお勧めします。
  4. 新しい提案をルートに追加します。制限制約を確認し、失敗する例外をスローします。
  5. トランザクションをコミットする

このようにして、データベースの同時実行制御を使用しています。それ以外の方法はないと思います。

これにより競合が発生しますが、それを最小限に抑えるためにいくつかの手順を実行できます。つまり、手順 3 で、選択した db 列にインデックスがあることを確認してください。これにより、ページ ロックではなく行ロックが発生します。

手順 3 でアップグレード ロックを使用すると、デッドロックが回避されます。基本的に、2 番目のユーザーが同じ集約ルートの提案を送信すると、データベースは最初のトランザクションがコミットされるまでそれを読み取らせません。

また、Proposal.RequestForProposalId に db インデックスを追加することを検討する必要があります。これは、Proposal が読み込まれる列であるため、パフォーマンスに役立ちます。そのテーブルのロックの範囲を最小限に抑えるのに役立つかどうかは 100% ではありませんが、可能性があります...

于 2010-11-05T09:44:27.610 に答える