Я начал думать о отслеживании изменений в графе сложных объектов в отключенном приложении. Я уже нашел несколько решений, но хотел бы знать, есть ли какая-либо передовая практика или какое решение вы используете и почему? Я передал тот же вопрос форум MSDN, но я получил только один ответ. Я хотел бы получить больше ответов, чтобы узнать из опыта других разработчиков.
Этот вопрос связан с .NET, поэтому для ответов с деталями реализации я предпочитаю ответы, связанные с .NET-миром, но я думаю, что это то же самое на других платформах.
Теоретическая проблема в моем случае определена в многоуровневой архитектуре (не обязательно n-уровневом в данный момент) следующим образом:
- Слой репозиториев, использующих ORM для борьбы с персистентностью (инструмент ORM не имеет значения на данный момент, но скорее всего это будет Entity Framework 4.0 или NHibernate).
- Набор чистых классов (постоянный неосведомленный = POCO, который эквивалентен POJO в мире Java), представляющий объекты домена. Хранилища сохраняют эти классы и возвращают их в качестве результатов запросов.
- Набор доменных служб, работающих с объектами домена.
- Фасадный слой, определяющий шлюз для бизнес-логики. Внутри он использует репозитории, службы домена и объекты домена. Объекты домена не отображаются - каждый фасадный метод использует набор специализированных объектов передачи данных для параметра и возвращаемого значения. Ответственность за каждый метод фасада заключается в преобразовании объекта домена в DTO и наоборот.
- Современное веб-приложение, использующее фасадный слой и DTO - я вызываю это отключенное приложение. Как правило, дизайн может измениться в будущем, так что слой Facade будет обернут слоем веб-сервиса, и веб-приложение будет потреблять эти услуги = > переход на 3-уровневую (сеть, бизнес-логику, базу данных).
Теперь предположим, что одним из объектов домена является Order, который имеет детали заказа (строки) и связанные с ними ордеры. Когда клиент запрашивает заказ на редактирование, он может изменять Заказ, добавлять, удалять или изменять любую деталь заказа и добавлять или удалять связанные Заказы. Все эти изменения выполняются на основе данных в веб-браузере - javascript и AJAX. Таким образом, все изменения отправляются в один снимок, когда клиент нажимает кнопку сохранения. Вопрос в том, как справиться с этими изменениями? Инструмент репозитория и ORM должен знать, какие объекты и отношения были изменены, вставлены или удалены. Я закончил с двумя "лучшими" решениями:
-
Сохранить начальное состояние DTO в скрытом поле (в худшем случае для сеанса). При получении запроса на сохранение изменений создайте новый DTO на основе полученных данных и второй DTO на основе сохраненных данных. Слейте эти два и отслеживайте изменения. Отправьте объединенный DTO на уровень фасада и используйте полученную информацию об изменениях для правильной настройки диаграммы сущности. Это требует некоторого ручного отслеживания изменений в объекте домена, так что информация об изменении может быть настроена с нуля, а затем передана в репозиторий - вот в чем я не очень доволен.
-
Не отслеживать изменения в DTO. При получении измененных данных на фасадном уровне создайте модифицированный объект и загрузите фактическое состояние из репозитория (как правило, дополнительный запрос к базе данных - это то, что мне не очень нравится) - объедините эти два объекта и автоматически отслеживайте изменения через прокси-объект, предоставленный инструментом ORM (Entity framework 4.0 и NHibernate позволяют это). Для обработки concurrency требуется особая осторожность, поскольку фактическое состояние не должно быть начальным состоянием.
Что вы думаете об этом? Что вы порекомендуете?
Я знаю, что некоторые из этих проблем можно избежать, используя кеширование на некоторых уровнях приложения, но это то, что я не хочу использовать в данный момент.
Мой интерес к этой теме идет еще дальше. Например, предположим, что приложение относится к 3-уровневой архитектуре, а клиент (веб-приложение) не будет записан в .NET. Классы DTO нельзя использовать повторно. Отслеживание изменений в DTO будет намного сложнее, потому что потребуется, чтобы другая команда разработчиков правильно внедряла механизм отслеживания в своих инструментах разработки.
Я считаю, что эти проблемы нужно решать во многих приложениях, пожалуйста, поделитесь опытом.