Поток StateMachine в модели master-detail - PullRequest
1 голос
/ 20 сентября 2011

Мне нужно задать сложный сценарий, поэтому я попытаюсь объяснить на примере.

Рассмотрим следующую модель:

public enum States { Created, Approved, Started, Completed }

public class Request {
    States State {get; set;}
    IEnumerable<RequestLine> Lines {get; set;}
}

public class RequestLine {
    States State {get; set;}
    Request Request {get; set;}
    IEnumerable<WorkOrder> WorkOrders {get; set;}
}   

public class WorkOrder {
    States State {get; set;}
    RequestLine RequestLine {get; set;}
    IEnumerable<WorkOrderAction> Actions {get; set;}
}

public class WorkOrderAction {
    States State {get; set;}
    WorkOrder WorkOrder {get; set;}
}

Итак, каждая запись имеет состояние, и все они связаны. Когда создается WorkOrderAction, я должен обновить состояние WorkOrder, затем состояние RequesTLine, а затем состояние запроса. Для каждой записи WorkOrderAction я должен проверить состояние других дочерних записей и обновить родительскую запись.

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

Существует ли общая концепция для связанных конечных автоматов?

Ответы [ 3 ]

2 голосов
/ 21 сентября 2011

Нам нужно знать только «других незавершенных детей».

  1. Мы можем перечислить все из них: foreach (parent.Children) if (child.State! = Completed). Однако при этом все они будут загружены, что приведет к снижению производительности
  2. Мы можем выполнить обратную передачу к базе данных, используя что-то вроде Execute (новый BinaryOperator («State», Completed, NotEquals), AggreagateOperand.Count).Это требует реструктуризации домена, и снижение производительности меньше, чем в предыдущем.
  3. Мы можем обновить элемент родительского элемента 'IncompletedChildren' (целое число), когда каждый дочерний элемент сохранен / удален / удален / добавлен.Родительский объект всегда загружается, поэтому мы можем определить, что родительский объект завершен, когда «IncompletedChildren == 0», пометить его как завершенный и рекурсивно принудительно завершить его.Никакой дополнительной загрузки в трафик нет (одно целое число не является «загрузочным» imho).Однако этот подход вызывает увеличение «OptimisticLoading» для каждого обновления «IncompletedChildren» - он делает этот подход неприменимым в некоторых сценариях.

Я бы рекомендовал второй подход.

PS: В нашей системе проектов / задач мы ввели вычисляемые поля с выражениями "Items [State <> Completed] .Count. Однако это не может работать в реальности. В большинстве случаев, по крайней мере, в нашей системе Completedсостояние не означало что все выполнено:)

0 голосов
/ 20 сентября 2011

Не совсем уверен, что я понимаю вопрос, но если вы спрашиваете об обеспечении «каскадного» целостности данных (каскадное обновление), то я бы рассмотрел настройку «отложенных» ограничений, которые будут откладывать проверку проверки ограничений до коммит выдается. Затем вы будете обновлять данные для родителя / ребенка по мере необходимости, а затем коммитить.

Вот ссылка на отложенные ограничения от Oracle.

0 голосов
/ 20 сентября 2011

Обычная практика на самом деле не имеет ничего общего с конечными автоматами. То есть конечные автоматы не являются чем-то особенным, когда дело доходит до обеспечения соблюдения правил целостности данных.

Если он должен работать правильно для всех пользователей, то имеет смысл реализовать его в триггерах. Только код, контролируемый dbms, может обеспечить соблюдение правил целостности данных для всех пользователей. (И всех пользователей включает администратора базы данных, лишенного сна, и ее инструменты командной строки.)

...