Как я могу обработать параллелизм с сохраненными вычисленными свойствами в совокупном корне через NHibernate? - PullRequest
3 голосов
/ 15 октября 2010

Мне необходимо сохранить вычисляемое свойство с агрегированным корнем. Расчет основан на дочерних объектах. Я использую root для добавления / удаления потомков с помощью методов домена, и эти методы обновляют свойство Calculate.

Дочерняя сущность может быть добавлена ​​в определенный корень несколькими пользователями системы. Например, пользователь A может добавить дочерний элемент в Root123, а пользователь B также может добавить дочерний элемент в 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 пользователя подают свои предложения примерно в одно и то же время? Пользовательский интерфейс видит, что предел еще не достигнут, и отображает веб-страницу для отправки предложения обоим пользователям. Когда первый пользователь подчиняется, все хорошо. Теперь со вторым пользователем все будет в порядке, пока первый пользователь отправляет информацию перед вторым, поэтому, когда второй пользователь отправляет данные, данные извлекаются из БД и предел будет точным.

Это спорный вопрос? Стоит ли полагаться на ограничения в БД (ProposalLimit> = ProposalCount) для тех редких случаев, когда 2 пользователя отправляют информацию почти одновременно?

1 Ответ

2 голосов
/ 05 ноября 2010

Если вы поместите проверку бизнес-правила (т.е. проверку лимита) внутри транзакции, все будет в порядке.То есть кнопка

  1. пользователя нажимает кнопку, которая запускает команду добавления предложения
  2. Код запускает новую транзакцию.См. здесь, чтобы узнать, как я предлагаю вам использовать транзакции
  3. Загрузите объект RequestForProposal из БД или обновите его.Я предлагаю вам использовать блокировку обновления.
  4. Добавьте новые предложения в корень.Проверьте ограничение ограничения, сгенерируйте исключение, если оно не выполнено.
  5. Подтвердите транзакцию

Делая это таким образом, вы используете базы данных средства управления параллелизмом .Я не думаю, что есть другой способ сделать это.

Это создаст некоторую конкуренцию, но вы можете сделать несколько шагов, чтобы минимизировать это.А именно, убедитесь, что на шаге 3 столбец БД, по которому вы выбрали, имеет индекс.Это приведет к блокировке строки вместо блокировки страницы.

Если вы используете блокировку обновления на шаге 3, это позволит избежать взаимоблокировок.Как правило, когда вторые пользователи отправляют предложение для того же Агрегированного корня, БД не позволит вам прочитать его, пока не будет зафиксирована первая транзакция.

Также следует рассмотреть возможность добавления индекса БД в Proposal.RequestForProposalId, это поможетпроизводительность, как это столбец, на котором загружены предложения.Я не на 100%, если это поможет минимизировать объем любых блокировок на этой таблице, но это может ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...